From b1a882f178d71d1462b5ee7e7ffde142928b5086 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 7 Feb 2014 16:52:00 +0100 Subject: Fix drawCachedGlyphs on RGBA8888 drawCachedGlyphs draws with the wrong color on RGBA8888. The issue is that the draw routines bitmapblit_quint32 and alphamapblit_quint32 while safe to use on rgba formats, needs to have the input color converted. This patch adds small wrapper functions for bitmapblit and alphamapblit that converts the formats. Two tests are extended to ensure we have test coverage. Change-Id: I5f99f3795eba46a69d4df5b167e6099024e9a060 Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 89 ++++++++++++++++++++--------------- src/gui/painting/qdrawhelper_avx.cpp | 1 + src/gui/painting/qdrawhelper_sse2.cpp | 7 +++ src/gui/painting/qdrawhelper_x86_p.h | 6 +++ 4 files changed, 66 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index c71d75cf94..865dab6597 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5605,7 +5605,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) } } -inline static void qt_bitmapblit_quint32(QRasterBuffer *rasterBuffer, +inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, int mapWidth, int mapHeight, int mapStride) @@ -5614,6 +5614,15 @@ inline static void qt_bitmapblit_quint32(QRasterBuffer *rasterBuffer, map, mapWidth, mapHeight, mapStride); } +inline static void qt_bitmapblit_rgba8888(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride) +{ + qt_bitmapblit_template(rasterBuffer, x, y, ARGB2RGBA(color), + map, mapWidth, mapHeight, mapStride); +} + inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, @@ -5725,11 +5734,11 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in } #endif -static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, - const uchar *map, - int mapWidth, int mapHeight, int mapStride, - const QClipData *clip) +static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) { const quint32 c = color; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); @@ -5820,10 +5829,19 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, } } -static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, - const uint *src, int mapWidth, int mapHeight, int srcStride, - const QClipData *clip) +static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) +{ + qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip); +} + +static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uint *src, int mapWidth, int mapHeight, int srcStride, + const QClipData *clip) { const quint32 c = color; @@ -5965,27 +5983,27 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = { blend_color_argb, qt_gradient_argb32, - qt_bitmapblit_quint32, - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_bitmapblit_argb32, + qt_alphamapblit_argb32, + qt_alphargbblit_argb32, qt_rectfill_argb32 }, // Format_ARGB32, { blend_color_generic, qt_gradient_argb32, - qt_bitmapblit_quint32, - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_bitmapblit_argb32, + qt_alphamapblit_argb32, + qt_alphargbblit_argb32, qt_rectfill_nonpremul_argb32 }, // Format_ARGB32_Premultiplied { blend_color_argb, qt_gradient_argb32, - qt_bitmapblit_quint32, - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_bitmapblit_argb32, + qt_alphamapblit_argb32, + qt_alphargbblit_argb32, qt_rectfill_argb32 }, // Format_RGB16 @@ -6049,42 +6067,39 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = { blend_color_generic, blend_src_generic, - qt_bitmapblit_quint32, + qt_bitmapblit_rgba8888, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_alphamapblit_rgba8888, #else 0, - 0, #endif + 0, qt_rectfill_rgba }, // Format_RGBA8888 { blend_color_generic, blend_src_generic, - qt_bitmapblit_quint32, + qt_bitmapblit_rgba8888, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_alphamapblit_rgba8888, #else 0, - 0, #endif + 0, qt_rectfill_nonpremul_rgba }, // Format_RGB8888_Premultiplied { blend_color_generic, blend_src_generic, - qt_bitmapblit_quint32, + qt_bitmapblit_rgba8888, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_alphamapblit_rgba8888, #else 0, - 0, #endif + 0, qt_rectfill_rgba } }; @@ -6173,9 +6188,9 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_avx; qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_avx; qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_avx; - qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_avx; - qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_avx; - qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_avx; + qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit8888_avx; + qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit8888_avx; + qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit8888_avx; extern void qt_scale_image_argb32_on_argb32_avx(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, @@ -6198,9 +6213,9 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse2; - qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_sse2; - qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_sse2; - qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2; + qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit8888_sse2; + qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit8888_sse2; + qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit8888_sse2; extern void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, diff --git a/src/gui/painting/qdrawhelper_avx.cpp b/src/gui/painting/qdrawhelper_avx.cpp index 7da6ce6a20..7d42525150 100644 --- a/src/gui/painting/qdrawhelper_avx.cpp +++ b/src/gui/painting/qdrawhelper_avx.cpp @@ -60,6 +60,7 @@ #define qt_memfill32_sse2 qt_memfill32_avx #define qt_memfill16_sse2 qt_memfill16_avx #define qt_bitmapblit32_sse2 qt_bitmapblit32_avx +#define qt_bitmapblit8888_sse2 qt_bitmapblit8888_avx #define qt_bitmapblit16_sse2 qt_bitmapblit16_avx #define QSimdSse2 QSimdAvx #define qt_fetch_radial_gradient_sse2 qt_fetch_radial_gradient_avx diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index a9dc5a7fb7..ea191c2ec5 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -470,6 +470,13 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, } } +void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride) +{ + qt_bitmapblit32_sse2(rasterBuffer, x, y, ARGB2RGBA(color), src, width, height, stride); +} + void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride) diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index d64b9cec39..aee508f641 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -63,6 +63,9 @@ void qt_memfill16_sse2(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); +void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride); void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); @@ -85,6 +88,9 @@ void qt_memfill16_avx(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_avx(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); +void qt_bitmapblit8888_avx(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride); void qt_bitmapblit16_avx(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); -- cgit v1.2.3 From c453571d753160313a8dcb3f3aa4667c34616a8f Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 25 Feb 2014 14:35:46 +0100 Subject: CSS parser: fix the pseudo-classes array length The pseudoclass array is declared with length "NumPseudos - 1", but the declaration has actually 44 elements, not 45. This caused a zero-initialized last element to be silently appended to the array. The zero-initialized element broke the sorting of the array, which in turn broke std::lower_bound usage (although of course the problem was there from before switching to the standard library algorithms). Task-number: QTBUG-36933 Change-Id: I8a02891fc36761b6ae72d15a0a8d6c6a96813947 Reviewed-by: Olivier Goffart --- src/gui/text/qcssparser_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index b087a2384a..123a53c5cc 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -508,7 +508,7 @@ const quint64 PseudoClass_EditFocus = Q_UINT64_C(0x0000080000000000); const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000); // The Any specifier is never generated, but can be used as a wildcard in searches. const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff); -const int NumPseudos = 46; +const int NumPseudos = 45; struct Pseudo { -- cgit v1.2.3 From 15ec9907f968f3c4ebe461617b448f5c8d05e5c5 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 24 Feb 2014 14:54:30 +0100 Subject: Cocoa Menu: Set keyboard modifiers when item is activated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems to be a regression from 4.8, which is not surprising since everything was rewritten for QPA. Task-number: QTBUG-36851 Change-Id: If89f8c9e6897fd1e02800f49e51baeb1ea181238 Reviewed-by: Morten Johan Sørvig Reviewed-by: James Turner --- src/plugins/platforms/cocoa/qcocoamenu.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 329c7a264a..aa6b71df31 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -127,6 +127,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); { QCocoaMenuItem *cocoaItem = reinterpret_cast([item tag]); QScopedLoopLevelCounter loopLevelCounter(QGuiApplicationPrivate::instance()->threadData); + QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; cocoaItem->activated(); } -- cgit v1.2.3 From bf0336a02502b3ed4d399c1cf5b4a56b1e858d42 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 19 Feb 2014 17:41:33 +0100 Subject: Cocoa Menus: Give platform menu ownership back to QWidgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to be in the situation where a QCocoaMenuItem owns a QCocoaMenu (because that item is a submenu), and then the actual QMenu "sees" that same QCocoaMenu being deleted. Instead, since all the QCocoaMenu* classes inherit QObject, we rely on meta-object properties to set the hierarchy and climb the hierarchy when guessing the menu item's role. This ammends most of commit 370e89f06465a4d61c7b. Task-number: QTBUG-36785 Change-Id: I0e03acb593e93061c8c6c1fdd161669cf0d2a293 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenu.mm | 8 ++++---- src/plugins/platforms/cocoa/qcocoamenuitem.h | 3 +++ src/plugins/platforms/cocoa/qcocoamenuitem.mm | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index aa6b71df31..35e8fdebb4 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -269,7 +269,7 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * QCocoaMenuItem *cocoaItem = static_cast(menuItem); QCocoaMenuItem *beforeItem = static_cast(before); - menuItem->setParent(this); + SET_COCOA_MENU_ANCESTOR(menuItem, this); cocoaItem->sync(); if (beforeItem) { int index = m_menuItems.indexOf(beforeItem); @@ -326,8 +326,8 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem) return; } - if (menuItem->parent() == this) - menuItem->setParent(0); + if (COCOA_MENU_ANCESTOR(menuItem) == this) + SET_COCOA_MENU_ANCESTOR(menuItem, 0); m_menuItems.removeOne(cocoaItem); if (!cocoaItem->isMerged()) { @@ -551,7 +551,7 @@ void QCocoaMenu::syncModalState(bool modal) void QCocoaMenu::setMenuBar(QCocoaMenuBar *menuBar) { m_menuBar = menuBar; - setParent(menuBar); + SET_COCOA_MENU_ANCESTOR(this, menuBar); } QCocoaMenuBar *QCocoaMenu::menuBar() const diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 1e69ed5a4b..b0169b9746 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -118,6 +118,9 @@ private: quintptr m_tag; }; +#define COCOA_MENU_ANCESTOR(m) ((m)->property("_qCocoaMenuAncestor").value()) +#define SET_COCOA_MENU_ANCESTOR(m, ancestor) (m)->setProperty("_qCocoaMenuAncestor", QVariant::fromValue(ancestor)) + QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 3bba1ee1d5..2246d2ce46 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -126,13 +126,13 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) { if (menu == m_menu) return; - if (m_menu && m_menu->parent() == this) - m_menu->setParent(0); + if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this) + SET_COCOA_MENU_ANCESTOR(m_menu, 0); QCocoaAutoReleasePool pool; m_menu = static_cast(menu); if (m_menu) { - m_menu->setParent(this); + SET_COCOA_MENU_ANCESTOR(m_menu, this); } else { // we previously had a menu, but no longer // clear out our item so the nexy sync() call builds a new one @@ -217,12 +217,12 @@ NSMenuItem *QCocoaMenuItem::sync() mergeItem = [loader preferencesMenuItem]; break; case TextHeuristicRole: { - QObject *p = parent(); + QObject *p = COCOA_MENU_ANCESTOR(this); int depth = 1; QCocoaMenuBar *menubar = 0; while (depth < 3 && p && !(menubar = qobject_cast(p))) { ++depth; - p = p->parent(); + p = COCOA_MENU_ANCESTOR(p); } if (depth == 3 || !menubar) break; // Menu item too deep in the hierarchy, or not connected to any menubar -- cgit v1.2.3 From f15d9e6ccd006a2b47b50ae755fbe9534748a2eb Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 6 Mar 2014 14:21:53 +0100 Subject: do not use fileno calls in forked child This fixes an issue that causes QProcess::start to silently fail on OS X 10.9. Apparently, fileno(stdout) locks the handle on OS X 10.9. It may happen that the parent process fflush()s stdout while the child has just been forked. The stdout lock of the parent is never released in the child and fileno(stdout) therefore locks forever. According to the fork documentation on opengroup.org one may only call async-signal-safe functions between fork and exec in the child. The fileno() function does not appear in the list of async-signal-safe functions. Also, fileno(stdout) and friends can be easily replaced by the standard constants STDOUT_FILENO etc. Done-with: Fawzi Mohamed Task-number: QTBUG-37306 Change-Id: I2b1f5f47cc48a1ad020fb0493a955d2bc27aeb47 Reviewed-by: Thiago Macieira (cherry picked from b2216bbe06b8be2bef6d8bc2ffff1337f6d23358) --- src/corelib/io/qprocess_unix.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 3c6d294916..8add9c56a7 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -880,18 +880,18 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv // copy the stdin socket if asked to (without closing on exec) if (inputChannelMode != QProcess::ForwardedInputChannel) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); + qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { if (processChannelMode != QProcess::ForwardedOutputChannel) - qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); + qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_safe_dup2(fileno(stdout), fileno(stderr), 0); + qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0); } else if (processChannelMode != QProcess::ForwardedErrorChannel) { - qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); + qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0); } } -- cgit v1.2.3 From 263f97f963360764b27d7298bcac678606800818 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 11 Mar 2014 16:23:10 +0100 Subject: Fix Mac Bearer when machine has no wifi This manifested itself for some continuous integration machine, all regular macs have wireless. In case there is no wifi, we would never emit updateCompleted(). Change-Id: I1c5b0da6e1d73fef2588beb1796207326d430e26 Reviewed-by: Gabriel de Dietrich Reviewed-by: Friedemann Kleint Reviewed-by: Lorn Potter --- src/plugins/bearer/corewlan/qcorewlanengine.mm | 2 ++ src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index dc2920360d..2d8b9be092 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -573,6 +573,8 @@ void QCoreWlanEngine::doRequestUpdate() scanThread->start(); } locker.unlock(); + if ([wifiInterfaces count] == 0) + networksChanged(); [autoreleasepool release]; } diff --git a/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm b/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm index 7044e9696b..057aec5487 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm @@ -631,6 +631,8 @@ void QCoreWlanEngine::doRequestUpdate() scanThread->start(); } locker.unlock(); + if ([wifiInterfaces count] == 0) + networksChanged(); [autoreleasepool release]; } -- cgit v1.2.3 From c026912e84df16a17b761ffb520b4f068e3739af Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 10 Mar 2014 11:34:56 +0100 Subject: Doc: Fix issue in QThread example code Added a missing reference operator to make the code example compile. Task-number: QTBUG-37359 Change-Id: Ie52f65ab3b325daf1ee3b368131e54c8a17f92ef Reviewed-by: Olivier Goffart Reviewed-by: Jerome Pasion --- src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp index fde37bb549..54c8f801cd 100644 --- a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp @@ -87,7 +87,7 @@ public: Controller() { Worker *worker = new Worker; worker->moveToThread(&workerThread); - connect(workerThread, &QThread::finished, worker, &QObject::deleteLater); + connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); connect(this, &Controller::operate, worker, &Worker::doWork); connect(worker, &Worker::resultReady, this, &Controller::handleResults); workerThread.start(); -- cgit v1.2.3 From 0541f65efaf15e87ba8abecc070b457ef7d89e35 Mon Sep 17 00:00:00 2001 From: Alejandro Exojo Date: Fri, 7 Mar 2014 12:17:22 +0100 Subject: Fix docs: QT_FATAL_WARNINGS acts when not empty Change-Id: If68b98459eab3186e2f3d44f087b753d2c57b79d Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira Reviewed-by: Kai Koehne --- src/corelib/global/qglobal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index c15305322b..108866b8df 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -3258,7 +3258,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) On Blackberry the message is sent to slogger2. This function does nothing if \c QT_NO_WARNING_OUTPUT was defined during compilation; it exits if the environment variable \c - QT_FATAL_WARNINGS is defined. + QT_FATAL_WARNINGS is not empty. This function takes a format string and a list of arguments, similar to the C printf() function. The format should be a Latin-1 -- cgit v1.2.3 From 0300f56133d20fabdd303f5109ccd0c7a1eda9f5 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 7 Mar 2014 14:36:20 +0100 Subject: Make android non-prefix shadow build usable Until now android developer build was not usable due to missing files. These files are only available after a make install. This patch aims to add that copy phase when building. Task-number: QTBUG-36901 Change-Id: If0a7e982899b8c18495c7cb6508184fa153b239d Reviewed-by: Oswald Buddenhagen --- src/android/java/java.pro | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/android/java/java.pro b/src/android/java/java.pro index 9d682e4f23..cff2d55d86 100644 --- a/src/android/java/java.pro +++ b/src/android/java/java.pro @@ -9,3 +9,17 @@ javaresources.files = \ javaresources.path = $$[QT_INSTALL_PREFIX]/src/android/java INSTALLS += javaresources + +!prefix_build:!equals(OUT_PWD, $$PWD) { + RETURN = $$escape_expand(\\n\\t) + equals(QMAKE_HOST.os, Windows) { + RETURN = $$escape_expand(\\r\\n\\t) + } + OUT_PATH = $$shell_path($$OUT_PWD) + + QMAKE_POST_LINK += \ + $${QMAKE_COPY} $$shell_path($$PWD/AndroidManifest.xml) $$OUT_PATH $$RETURN \ + $${QMAKE_COPY} $$shell_path($$PWD/version.xml) $$OUT_PATH $$RETURN \ + $${QMAKE_COPY_DIR} $$shell_path($$PWD/res) $$OUT_PATH $$RETURN \ + $${QMAKE_COPY_DIR} $$shell_path($$PWD/src) $$OUT_PATH +} -- cgit v1.2.3 From afcaaea4c6f4e71e051ed5e00d38f7f4d9890719 Mon Sep 17 00:00:00 2001 From: Janne Anttila Date: Fri, 28 Feb 2014 14:37:18 +0200 Subject: Implement QStandardPaths::GenericConfigLocation for WinRT. Same logic for locaton used as in other Windows variants. Change-Id: I5f71710d28ea1338748c9bd41d48bba15e674baa Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/corelib/io/qstandardpaths_winrt.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp index 9b6a088a30..bd72de11bb 100644 --- a/src/corelib/io/qstandardpaths_winrt.cpp +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -74,6 +74,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) switch (type) { case ConfigLocation: // same as DataLocation, on Windows + case GenericConfigLocation: // same as GenericDataLocation, on Windows case DataLocation: case GenericDataLocation: { ComPtr applicationDataStatics; -- cgit v1.2.3 From 1bd56022a526b7f16c888921c82c4b22a89decb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 26 Feb 2014 12:27:37 +0100 Subject: Cancel NSURLConnections before releasing them. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-37042 Change-Id: I7ddcbc315b4b720e7da7880fc00731c28beb4bb2 Reviewed-by: Peter Hartmann Reviewed-by: Tor Arne Vestbø --- src/network/access/qnetworkreplynsurlconnectionimpl.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl.mm b/src/network/access/qnetworkreplynsurlconnectionimpl.mm index 293a505912..d49324918e 100644 --- a/src/network/access/qnetworkreplynsurlconnectionimpl.mm +++ b/src/network/access/qnetworkreplynsurlconnectionimpl.mm @@ -128,6 +128,7 @@ QNetworkReplyNSURLConnectionImplPrivate::QNetworkReplyNSURLConnectionImplPrivate QNetworkReplyNSURLConnectionImplPrivate::~QNetworkReplyNSURLConnectionImplPrivate() { + [urlConnection cancel]; [urlConnection release]; [urlConnectionDelegate release]; if (readStream) -- cgit v1.2.3 From 961b24eed24185cdd16ca347f6ca2580d86ea9c6 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Feb 2014 12:57:17 +0100 Subject: Don't show evaluation popup for unsupported evaluation Do not show the popup for unsupported evaluations on every launch of a QWidget based application. This is causing problems e.g. for applications that are run by Qt Creator in the background, like qmlpuppet. Instead, we'll show a similar dialog on Qt Creator startup. Change-Id: I6b44c24865ed6992a70f8a9dd0bcd08a4744cb28 Reviewed-by: Iikka Eklund Reviewed-by: Sami Makkonen Reviewed-by: Alex Blasche --- src/corelib/kernel/qtcore_eval.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp index 59656883f1..40c1157fb4 100644 --- a/src/corelib/kernel/qtcore_eval.cpp +++ b/src/corelib/kernel/qtcore_eval.cpp @@ -529,8 +529,6 @@ void qt_gui_eval_init(QCoreApplicationPrivate::Type type) box.exec(); ::exit(0); } else { - EvalMessageBox *box = new EvalMessageBox(false); - box->show(); Q_UNUSED(new QGuiFuriCuri()); } } -- cgit v1.2.3 From e6cb06a8354a1423a7fc53af96a55e1e156bdcc2 Mon Sep 17 00:00:00 2001 From: David Fries Date: Fri, 7 Mar 2014 15:40:54 -0600 Subject: correct send vs sent grammar Correct the tense of send vs sent in comments and documentation. Change-Id: I1c5ce9a7b1e49b8b0e8dcfde7d732e4c69acf73a Reviewed-by: Kurt Pattyn Reviewed-by: Laszlo Agocs --- src/gui/kernel/qevent.cpp | 10 +++++----- src/network/access/qhttpnetworkreply.cpp | 4 ++-- src/network/access/qhttpnetworkrequest.cpp | 2 +- src/widgets/graphicsview/qgraphicsitem.cpp | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 295380a93c..92d9871dc5 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4361,13 +4361,13 @@ void QTouchEvent::TouchPoint::setFlags(InfoFlags flags) \ingroup events \inmodule QtGui - \brief The QScrollPrepareEvent class is send in preparation of a scrolling. + \brief The QScrollPrepareEvent class is sent in preparation of scrolling. - The scroll prepare event is send before scrolling (usually by QScroller) is started. + The scroll prepare event is sent before scrolling (usually by QScroller) is started. The object receiving this event should set viewportSize, maxContentPos and contentPos. It also should accept this event to indicate that scrolling should be started. - It is not guaranteed that a QScrollEvent will be send after an acceepted + It is not guaranteed that a QScrollEvent will be sent after an acceepted QScrollPrepareEvent, e.g. in a case where the maximum content position is (0,0). \sa QScrollEvent, QScroller @@ -4462,9 +4462,9 @@ void QScrollPrepareEvent::setContentPos(const QPointF &pos) \ingroup events \inmodule QtGui - \brief The QScrollEvent class is send when scrolling. + \brief The QScrollEvent class is sent when scrolling. - The scroll event is send to indicate that the receiver should be scrolled. + The scroll event is sent to indicate that the receiver should be scrolled. Usually the receiver should be something visual like QWidget or QGraphicsObject. Some care should be taken that no conflicting QScrollEvents are sent from two diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 2a7e6ed638..b057fee144 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -363,7 +363,7 @@ bool QHttpNetworkReplyPrivate::isCompressed() void QHttpNetworkReplyPrivate::removeAutoDecompressHeader() { // The header "Content-Encoding = gzip" is retained. - // Content-Length is removed since the actual one send by the server is for compressed data + // Content-Length is removed since the actual one sent by the server is for compressed data QByteArray name("content-length"); QList >::Iterator it = fields.begin(), end = fields.end(); @@ -921,7 +921,7 @@ qint64 QHttpNetworkReplyPrivate::getChunkSize(QAbstractSocket *socket, qint64 *c bool QHttpNetworkReplyPrivate::shouldEmitSignals() { // for 401 & 407 don't emit the data signals. Content along with these - // responses are send only if the authentication fails. + // responses are sent only if the authentication fails. return (statusCode != 401 && statusCode != 407); } diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 6e9f1216c3..8ad04c9885 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -120,7 +120,7 @@ QByteArray QHttpNetworkRequest::uri(bool throughProxy) const { QUrl::FormattingOptions format(QUrl::RemoveFragment | QUrl::RemoveUserInfo | QUrl::FullyEncoded); - // for POST, query data is send as content + // for POST, query data is sent as content if (d->operation == QHttpNetworkRequest::Post && !d->uploadByteDevice) format |= QUrl::RemoveQuery; // for requests through proxy, the Request-URI contains full url diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index ae2423400a..292b0419ca 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -472,7 +472,7 @@ notification). \value ItemTransformChange The item's transformation matrix changes. This - notification is send if the ItemSendsGeometryChanges flag is enabled, and + notification is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's local transformation matrix changes (i.e., as a result of calling setTransform(). The value argument is the new matrix (i.e., a QTransform); to get the old matrix, call transform(). Do not call @@ -6604,7 +6604,7 @@ void QGraphicsItem::removeSceneEventFilter(QGraphicsItem *filterItem) Reimplementing this function in a subclass makes it possible for the item to be used as an event filter for other items, - intercepting all the events send to those items before they are + intercepting all the events sent to those items before they are able to respond. Reimplementations must return true to prevent further processing of -- cgit v1.2.3 From c6bb371b4bce8163bfac2b77a9a7e0f7cb9ad4bc Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 11 Mar 2014 15:28:14 +0100 Subject: fix warning Change-Id: I7afedbf679ae1c8467eea749e79eb10f2516d039 Reviewed-by: Oliver Wolff Reviewed-by: Andrew Knight --- src/network/socket/qlocalserver_tcp.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/network/socket/qlocalserver_tcp.cpp b/src/network/socket/qlocalserver_tcp.cpp index 39e7babf71..de4acd9111 100644 --- a/src/network/socket/qlocalserver_tcp.cpp +++ b/src/network/socket/qlocalserver_tcp.cpp @@ -80,8 +80,6 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) bool QLocalServerPrivate::listen(qintptr socketDescriptor) { - Q_Q(QLocalServer); - return tcpServer.setSocketDescriptor(socketDescriptor); } -- cgit v1.2.3 From 04a632c88a243fb0caac6fc0c71288210c18232e Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 11 Mar 2014 15:28:35 +0100 Subject: fix namespaced WinRT build Change-Id: I613a737600f85ef90155e3b8647197b4fd092998 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/network/socket/qnativesocketengine_winrt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 2a61325471..4b2d1c372e 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -549,9 +549,9 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) Q_D(QNativeSocketEngine); qint64 bytesWritten = -1; if (d->socketType == QAbstractSocket::TcpSocket) - bytesWritten = ::nativeWrite(d->tcp, data, len); + bytesWritten = nativeWrite(d->tcp, data, len); else if (d->socketType == QAbstractSocket::UdpSocket) - bytesWritten = ::nativeWrite(d->udp, data, len); + bytesWritten = nativeWrite(d->udp, data, len); if (bytesWritten != -1 && d->notifyOnWrite) writeNotification(); return bytesWritten; -- cgit v1.2.3 From d38786debadf8b5673f4e5706ea6c0f10129268d Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 7 Mar 2014 15:57:28 +0200 Subject: WinRT: Separate backing store initialization to be more robust If the GL context cannot be made current in the backing store's constructor, the framebuffer resources won't be allocated. Fix this by creating an initialization routine that can be called again if it fails. The issue was revealed by the GUI Analog Clock demo, which creates the backing store before the window has a native handle. Task-number: QTBUG-36008 Change-Id: I875f8183eff60908fc2b46f441bb553b42ff500d Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtbackingstore.cpp | 32 ++++++++++++++++++---- src/plugins/platforms/winrt/qwinrtbackingstore.h | 2 ++ 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp index 10136dbead..9b623048af 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -207,14 +207,24 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window) , m_fbo(0) , m_texture(0) , m_screen(static_cast(window->screen()->handle())) + , m_initialized(false) { window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap +} - m_context->setFormat(window->requestedFormat()); - m_context->setScreen(window->screen()); - m_context->create(); +bool QWinRTBackingStore::initialize() +{ + if (m_initialized) + return true; + + m_context->setFormat(window()->requestedFormat()); + m_context->setScreen(window()->screen()); + if (!m_context->create()) + return false; + + if (!m_context->makeCurrent(window())) + return false; - m_context->makeCurrent(window); glGenFramebuffers(1, &m_fbo); glGenRenderbuffers(1, &m_rbo); glGenTextures(1, &m_texture); @@ -258,11 +268,14 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window) glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size()); #endif m_context->doneCurrent(); - resize(window->size(), QRegion()); + m_initialized = true; + return true; } QWinRTBackingStore::~QWinRTBackingStore() { + if (!m_initialized) + return; glDeleteBuffers(1, &m_fbo); glDeleteRenderbuffers(1, &m_rbo); glDeleteTextures(1, &m_texture); @@ -277,6 +290,8 @@ QPaintDevice *QWinRTBackingStore::paintDevice() void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(offset) + if (m_size.isEmpty()) + return; const QImage *image = static_cast(m_paintDevice.data()); @@ -334,10 +349,16 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents) { Q_UNUSED(staticContents) + if (!initialize()) + return; + if (m_size == size) return; m_size = size; + if (m_size.isEmpty()) + return; + m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied)); m_context->makeCurrent(window()); @@ -360,6 +381,7 @@ void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents void QWinRTBackingStore::beginPaint(const QRegion ®ion) { Q_UNUSED(region) + resize(window()->size(), QRegion()); } void QWinRTBackingStore::endPaint() diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index 8be549b441..726f7c838f 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -62,6 +62,8 @@ public: void resize(const QSize &size, const QRegion &staticContents); private: + bool initialize(); + bool m_initialized; QSize m_size; QScopedPointer m_paintDevice; QScopedPointer m_context; -- cgit v1.2.3 From a2a954da008a0d2b0ae0425f3d2dd55c89bfae59 Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Sat, 8 Mar 2014 15:20:02 +0100 Subject: QNX: Fix screen event handling Return code was misinterpreted. Change-Id: I917db0879384a4997ff154ab25e56fbada55c0e4 Reviewed-by: Fabian Bumberger --- src/plugins/platforms/qnx/qqnxscreeneventthread.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp index 156ba8a780..b66de3cac5 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp @@ -103,10 +103,10 @@ void QQnxScreenEventThread::run() Q_SCREEN_CHECKERROR(screen_create_event(&event), "Failed to create screen event"); // block until screen event is available - const int result = screen_get_event(m_screenContext, event, -1); - Q_SCREEN_CRITICALERROR(result, "Failed to get screen event"); + const int error = screen_get_event(m_screenContext, event, -1); + Q_SCREEN_CRITICALERROR(error, "Failed to get screen event"); // Only allow 50 consecutive errors before we exit the thread - if (!result) { + if (error) { errorCounter++; if (errorCounter > 50) m_quit = true; -- cgit v1.2.3 From 563342d7ef7e490239cba6d335849ebb91983b9a Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Wed, 5 Mar 2014 10:25:31 +0100 Subject: BlackBerry: Improve platform specific documentation Updated BlackBerry specific documentation around QSettings to make the differences more obvious for developers. Change-Id: Ib9acc2409379a836713f1a7e9d6189585a35aa61 Reviewed-by: Kevin Krammer Reviewed-by: Erin Rahnenfuehrer Reviewed-by: Rafael Roquetto Reviewed-by: Fabian Bumberger --- src/corelib/io/qsettings.cpp | 13 +++++++++++-- src/corelib/kernel/qcoreapplication.cpp | 9 +++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index a3727a6a4b..0406aeb501 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -2369,6 +2369,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, stored in the following registry path: \c{HKEY_LOCAL_MACHINE\Software\WOW6432node}. + On BlackBerry only a single file is used (see \l{Platform Limitations}). + If the file format is NativeFormat, this is "Settings/MySoft/Star Runner.conf" + in the application's home directory. + If the file format is IniFormat, the following files are used on Unix and Mac OS X: @@ -2393,8 +2397,12 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, %COMMON_APPDATA% path is usually \tt{C:\\Documents and Settings\\All Users\\Application Data}. + On BlackBerry only a single file is used (see \l{Platform Limitations}). + If the file format is IniFormat, this is "Settings/MySoft/Star Runner.ini" + in the application's home directory. + The paths for the \c .ini and \c .conf files can be changed using - setPath(). On Unix and Mac OS X, the user can override them by by + setPath(). On Unix and Mac OS X, the user can override them by setting the \c XDG_CONFIG_HOME environment variable; see setPath() for details. @@ -2498,7 +2506,8 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, allowed to read or write outside of this sandbox. This involves the following limitations: \list - \li As there is only a single scope the scope is simply ignored. + \li As there is only a single scope the scope is simply ignored, + i.e. there is no difference between SystemScope and UserScope. \li The \l{Fallback Mechanism} is not applied, i.e. only a single location is considered. \li It is advised against setting and using custom file paths. diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e8bcc449e9..bb2feee71e 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2217,6 +2217,9 @@ QStringList QCoreApplication::arguments() organizationName(). On all other platforms, QSettings uses organizationName() as the organization. + On BlackBerry this property is read-only. It is obtained from the + BAR application descriptor file. + \sa organizationDomain, applicationName */ @@ -2294,6 +2297,9 @@ QString QCoreApplication::organizationDomain() If not set, the application name defaults to the executable name (since 5.0). + On BlackBerry this property is read-only. It is obtained from the + BAR application descriptor file. + \sa organizationName, organizationDomain, applicationVersion, applicationFilePath() */ /*! @@ -2335,6 +2341,9 @@ Q_CORE_EXPORT QString qt_applicationName_noFallback() \since 4.4 \brief the version of this application + On BlackBerry this property is read-only. It is obtained from the + BAR application descriptor file. + \sa applicationName, organizationName, organizationDomain */ /*! -- cgit v1.2.3 From 8bbc1eaeb692368ae896072b24eb1a1b8d469cad Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 10 Mar 2014 16:09:51 +0100 Subject: docs: QApplication::startDragDistance default value is 10 This comes from QPlatformTheme::defaultThemeHint(). Change-Id: I12a9add3af65e819a06b66d958acb8f21cfe0e13 Reviewed-by: Jerome Pasion Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qapplication.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 9e221c1bf4..cb6f4aeecd 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2691,7 +2691,8 @@ void QApplication::setStartDragDistance(int l) Qt uses this value internally, e.g. in QFileDialog. - The default value is 4 pixels. + The default value (if the platform doesn't provide a different default) + is 10 pixels. \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop} */ -- cgit v1.2.3 From 48e6352d4c5f0cfd7341b029cc8151b968a7080d Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 11 Mar 2014 14:18:56 +0100 Subject: Cocoa: Fix crash when closing window from title bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some mouse event may result in the window being deleted so we need to take extra precaution when calling the super class' 'sendEvent:' method. Task-number: QTBUG-37287 Change-Id: Idf89ea177c78053bcdef52c54a197409e20bf38e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.h | 1 + src/plugins/platforms/cocoa/qcocoawindow.mm | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 67cac41383..9128b05746 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -80,6 +80,7 @@ typedef NSWindow QCocoaNSWindow; - (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow; - (void)handleWindowEvent:(NSEvent *)theEvent; +- (void) clearWindow; @end diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index f1f88a13dd..c2a0c81b31 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -155,7 +155,14 @@ static bool isMouseEvent(NSEvent *ev) } } + // The call to -[NSWindow sendEvent] may result in the window being deleted + // (e.g., when closing the window by pressing the title bar close button). + [self retain]; [self.window superSendEvent:theEvent]; + bool windowStillAlive = self.window != nil; // We need to read before releasing + [self release]; + if (!windowStillAlive) + return; if (!self.window.delegate) return; // Already detached, pending NSAppKitDefined event @@ -179,6 +186,11 @@ static bool isMouseEvent(NSEvent *ev) self.window.delegate = nil; } +- (void)clearWindow +{ + _window = nil; +} + - (void)dealloc { _window = nil; @@ -259,6 +271,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)dealloc { + [_helper clearWindow]; [_helper release]; _helper = nil; [super dealloc]; @@ -319,6 +332,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)dealloc { + [_helper clearWindow]; [_helper release]; _helper = nil; [super dealloc]; -- cgit v1.2.3 From 45f264b682e0b2ad7a162bd75b702837fe04c06a Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 10 Mar 2014 10:16:01 +0100 Subject: QGtkStyle: remove file dialog functionality GTK+ 2.x file dialogs are now implemented in QGtk2PlatformTheme Change-Id: I2babd6a35e7abd606ec5d047abbefbe3f0fbb892 Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge Reviewed-by: David Faure --- src/widgets/styles/qgtkstyle.cpp | 19 +-- src/widgets/styles/qgtkstyle_p.cpp | 256 ------------------------------------- src/widgets/styles/qgtkstyle_p_p.h | 61 --------- 3 files changed, 2 insertions(+), 334 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 9ad0484bc2..9fa056960a 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -471,15 +471,8 @@ void QGtkStyle::polish(QApplication *app) QApplicationPrivate::setSystemPalette(standardPalette()); QApplicationPrivate::setSystemFont(d->getThemeFont()); d->applyCustomPaletteHash(); - if (!d->isKDE4Session()) { -#ifndef QT_NO_FILEDIALOG - qt_filedialog_open_filename_hook = &QGtkStylePrivate::openFilename; - qt_filedialog_save_filename_hook = &QGtkStylePrivate::saveFilename; - qt_filedialog_open_filenames_hook = &QGtkStylePrivate::openFilenames; - qt_filedialog_existing_directory_hook = &QGtkStylePrivate::openDirectory; -#endif + if (!d->isKDE4Session()) qApp->installEventFilter(&d->filter); - } } } @@ -493,16 +486,8 @@ void QGtkStyle::unpolish(QApplication *app) QCommonStyle::unpolish(app); QPixmapCache::clear(); - if (app->desktopSettingsAware() && d->isThemeAvailable() - && !d->isKDE4Session()) { -#ifndef QT_NO_FILEDIALOG - qt_filedialog_open_filename_hook = 0; - qt_filedialog_save_filename_hook = 0; - qt_filedialog_open_filenames_hook = 0; - qt_filedialog_existing_directory_hook = 0; -#endif + if (app->desktopSettingsAware() && d->isThemeAvailable() && !d->isKDE4Session()) qApp->removeEventFilter(&d->filter); - } } /*! diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp index c53a21e59a..2bd978bcb8 100644 --- a/src/widgets/styles/qgtkstyle_p.cpp +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -180,20 +180,6 @@ Ptr_pango_font_description_get_weight QGtkStylePrivate::pango_font_description_g Ptr_pango_font_description_get_family QGtkStylePrivate::pango_font_description_get_family = 0; Ptr_pango_font_description_get_style QGtkStylePrivate::pango_font_description_get_style = 0; -Ptr_gtk_file_filter_new QGtkStylePrivate::gtk_file_filter_new = 0; -Ptr_gtk_file_filter_set_name QGtkStylePrivate::gtk_file_filter_set_name = 0; -Ptr_gtk_file_filter_add_pattern QGtkStylePrivate::gtk_file_filter_add_pattern = 0; -Ptr_gtk_file_chooser_add_filter QGtkStylePrivate::gtk_file_chooser_add_filter = 0; -Ptr_gtk_file_chooser_set_filter QGtkStylePrivate::gtk_file_chooser_set_filter = 0; -Ptr_gtk_file_chooser_get_filter QGtkStylePrivate::gtk_file_chooser_get_filter = 0; -Ptr_gtk_file_chooser_dialog_new QGtkStylePrivate::gtk_file_chooser_dialog_new = 0; -Ptr_gtk_file_chooser_set_current_folder QGtkStylePrivate::gtk_file_chooser_set_current_folder = 0; -Ptr_gtk_file_chooser_get_filename QGtkStylePrivate::gtk_file_chooser_get_filename = 0; -Ptr_gtk_file_chooser_get_filenames QGtkStylePrivate::gtk_file_chooser_get_filenames = 0; -Ptr_gtk_file_chooser_set_current_name QGtkStylePrivate::gtk_file_chooser_set_current_name = 0; -Ptr_gtk_dialog_run QGtkStylePrivate::gtk_dialog_run = 0; -Ptr_gtk_file_chooser_set_filename QGtkStylePrivate::gtk_file_chooser_set_filename = 0; - Ptr_gdk_pixbuf_get_pixels QGtkStylePrivate::gdk_pixbuf_get_pixels = 0; Ptr_gdk_pixbuf_get_width QGtkStylePrivate::gdk_pixbuf_get_width = 0; Ptr_gdk_pixbuf_get_height QGtkStylePrivate::gdk_pixbuf_get_height = 0; @@ -356,21 +342,6 @@ void QGtkStylePrivate::resolveGtk() const gtk_widget_destroy = (Ptr_gtk_widget_destroy)libgtk.resolve("gtk_widget_destroy"); gtk_widget_realize = (Ptr_gtk_widget_realize)libgtk.resolve("gtk_widget_realize"); - gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); - gtk_file_filter_new = (Ptr_gtk_file_filter_new)libgtk.resolve("gtk_file_filter_new"); - gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)libgtk.resolve("gtk_file_filter_set_name"); - gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)libgtk.resolve("gtk_file_filter_add_pattern"); - gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)libgtk.resolve("gtk_file_chooser_add_filter"); - gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)libgtk.resolve("gtk_file_chooser_set_filter"); - gtk_file_chooser_get_filter = (Ptr_gtk_file_chooser_get_filter)libgtk.resolve("gtk_file_chooser_get_filter"); - gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)libgtk.resolve("gtk_file_chooser_dialog_new"); - gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); - gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)libgtk.resolve("gtk_file_chooser_get_filename"); - gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)libgtk.resolve("gtk_file_chooser_get_filenames"); - gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)libgtk.resolve("gtk_file_chooser_set_current_name"); - gtk_dialog_run = (Ptr_gtk_dialog_run)libgtk.resolve("gtk_dialog_run"); - gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)libgtk.resolve("gtk_file_chooser_set_filename"); - gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)libgtk.resolve("gdk_pixbuf_get_pixels"); gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)libgtk.resolve("gdk_pixbuf_get_width"); gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)libgtk.resolve("gdk_pixbuf_get_height"); @@ -881,233 +852,6 @@ QFont QGtkStylePrivate::getThemeFont() return font; } - -// ----------- Native file dialogs ----------- - -// Extract filter list from expressions of type: foo (*.a *.b *.c)" -QStringList QGtkStylePrivate::extract_filter(const QString &rawFilter) -{ - QString result = rawFilter; - QRegExp r(QString::fromLatin1("^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$")); - int index = r.indexIn(result); - if (index >= 0) - result = r.cap(2); - return result.split(QLatin1Char(' ')); -} - -extern QStringList qt_make_filter_list(const QString &filter); - -#ifndef QT_NO_FILEDIALOG -void QGtkStylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, - const QString &dir, const QString &filter, QString *selectedFilter, - QFileDialog::Options options, bool isSaveDialog, - QHash *filterMap) -{ - g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL); - g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL); - if (!filter.isEmpty()) { - QStringList filters = qt_make_filter_list(filter); - foreach (const QString &rawfilter, filters) { - GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_filter_new (); - QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); - QStringList extensions = extract_filter(rawfilter); - QGtkStylePrivate::gtk_file_filter_set_name(gtkFilter, qPrintable(name.isEmpty() ? extensions.join(QLS(", ")) : name)); - - foreach (const QString &fileExtension, extensions) { - // Note Gtk file dialogs are by default case sensitive - // and only supports basic glob syntax so we - // rewrite .xyz to .[xX][yY][zZ] - QString caseInsensitive; - for (int i = 0 ; i < fileExtension.length() ; ++i) { - QChar ch = fileExtension.at(i); - if (ch.isLetter()) { - caseInsensitive.append( - QLatin1Char('[') + - ch.toLower() + - ch.toUpper() + - QLatin1Char(']')); - } else { - caseInsensitive.append(ch); - } - } - QGtkStylePrivate::gtk_file_filter_add_pattern (gtkFilter, qPrintable(caseInsensitive)); - - } - if (filterMap) - filterMap->insert(gtkFilter, rawfilter); - QGtkStylePrivate::gtk_file_chooser_add_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); - if (selectedFilter && (rawfilter == *selectedFilter)) - QGtkStylePrivate::gtk_file_chooser_set_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); - } - } - - // Using the currently active window is not entirely correct, however - // it gives more sensible behavior for applications that do not provide a - // parent - QWidget *modalFor = parent ? parent->window() : qApp->activeWindow(); - if (modalFor) { - QGtkStylePrivate::gtk_widget_realize(gtkFileChooser); // Creates X window -#ifndef Q_OS_MAC - XSetTransientForHint(QGtkStylePrivate::gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), - QGtkStylePrivate::gdk_x11_drawable_get_xid(gtkFileChooser->window), - modalFor->winId()); -#ifdef Q_WS_X11 - QGtkStylePrivate::gdk_x11_window_set_user_time (gtkFileChooser->window, QX11Info::appUserTime()); -#endif -#endif - } - - QFileInfo fileinfo(dir); - if (dir.isEmpty()) - fileinfo.setFile(QDir::currentPath()); - fileinfo.makeAbsolute(); - if (fileinfo.isDir()) { - QGtkStylePrivate::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); - } else if (isSaveDialog) { - QGtkStylePrivate::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.absolutePath())); - QGtkStylePrivate::gtk_file_chooser_set_current_name((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.fileName())); - } else { - QGtkStylePrivate::gtk_file_chooser_set_filename((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); - } -} - -QString QGtkStylePrivate::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) -{ - QHash filterMap; - GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); - - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - modal_widget.createWinId(); - QGuiApplicationPrivate::showModalWindow(modal_widget.windowHandle()); - - QString filename; - if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); - filename = QString::fromUtf8(gtk_filename); - g_free (gtk_filename); - if (selectedFilter) { - GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); - *selectedFilter = filterMap.value(gtkFilter); - } - } - - QApplicationPrivate::hideModalWindow(modal_widget.windowHandle()); - gtk_widget_destroy (gtkFileChooser); - return filename; -} - - -QString QGtkStylePrivate::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) -{ - QHash filterMap; - GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - setupGtkFileChooser(gtkFileChooser, parent, dir, QString(), 0, options); - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - modal_widget.createWinId(); - QGuiApplicationPrivate::showModalWindow(modal_widget.windowHandle()); - - QString filename; - if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); - filename = QString::fromUtf8(gtk_filename); - g_free (gtk_filename); - } - - QApplicationPrivate::hideModalWindow(modal_widget.windowHandle()); - gtk_widget_destroy (gtkFileChooser); - return filename; -} - -QStringList QGtkStylePrivate::openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) -{ - QStringList filenames; - QHash filterMap; - GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); - g_object_set(gtkFileChooser, "select-multiple", gboolean(true), NULL); - - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - modal_widget.createWinId(); - QGuiApplicationPrivate::showModalWindow(modal_widget.windowHandle()); - - if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - GSList *gtk_file_names = QGtkStylePrivate::gtk_file_chooser_get_filenames((GtkFileChooser*)gtkFileChooser); - for (GSList *iterator = gtk_file_names ; iterator; iterator = iterator->next) - filenames << QString::fromUtf8((const char*)iterator->data); - g_slist_free(gtk_file_names); - if (selectedFilter) { - GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); - *selectedFilter = filterMap.value(gtkFilter); - } - } - - QApplicationPrivate::hideModalWindow(modal_widget.windowHandle()); - gtk_widget_destroy (gtkFileChooser); - return filenames; -} - -QString QGtkStylePrivate::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) -{ - QHash filterMap; - GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true, &filterMap); - - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - modal_widget.createWinId(); - QGuiApplicationPrivate::showModalWindow(modal_widget.windowHandle()); - - QString filename; - if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); - filename = QString::fromUtf8(gtk_filename); - g_free (gtk_filename); - if (selectedFilter) { - GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); - *selectedFilter = filterMap.value(gtkFilter); - } - } - - QApplicationPrivate::hideModalWindow(modal_widget.windowHandle()); - gtk_widget_destroy (gtkFileChooser); - return filename; -} -#endif - QIcon QGtkStylePrivate::getFilesystemIcon(const QFileInfo &info) { QIcon icon; diff --git a/src/widgets/styles/qgtkstyle_p_p.h b/src/widgets/styles/qgtkstyle_p_p.h index 6f3759bd9e..1a8aa77042 100644 --- a/src/widgets/styles/qgtkstyle_p_p.h +++ b/src/widgets/styles/qgtkstyle_p_p.h @@ -200,23 +200,6 @@ typedef gint (*Ptr_pango_font_description_get_size) (const PangoFontDescription typedef PangoWeight (*Ptr_pango_font_description_get_weight) (const PangoFontDescription *); typedef const char* (*Ptr_pango_font_description_get_family) (const PangoFontDescription *); typedef PangoStyle (*Ptr_pango_font_description_get_style) (const PangoFontDescription *desc); -typedef gboolean (*Ptr_gtk_file_chooser_set_current_folder)(GtkFileChooser *, const gchar *); -typedef GtkFileFilter* (*Ptr_gtk_file_filter_new)(void); -typedef void (*Ptr_gtk_file_filter_set_name)(GtkFileFilter *, const gchar *); -typedef void (*Ptr_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern); -typedef void (*Ptr_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -typedef void (*Ptr_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -typedef GtkFileFilter* (*Ptr_gtk_file_chooser_get_filter)(GtkFileChooser *chooser); -typedef gchar* (*Ptr_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); -typedef GSList* (*Ptr_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); -typedef GtkWidget* (*Ptr_gtk_file_chooser_dialog_new)(const gchar *title, - GtkWindow *parent, - GtkFileChooserAction action, - const gchar *first_button_text, - ...); -typedef void (*Ptr_gtk_file_chooser_set_current_name) (GtkFileChooser *, const gchar *); -typedef gboolean (*Ptr_gtk_file_chooser_set_filename) (GtkFileChooser *chooser, const gchar *name); -typedef gint (*Ptr_gtk_dialog_run) (GtkDialog*); typedef void (*Ptr_gtk_border_free)(GtkBorder *); typedef void (*Ptr_gtk_widget_get_allocation) (GtkWidget*, GtkAllocation*); typedef void (*Ptr_gtk_widget_set_allocation) (GtkWidget*, const GtkAllocation*); @@ -242,22 +225,6 @@ typedef Display* (*Ptr_gdk_x11_drawable_get_xdisplay) ( GdkDrawable *); QT_BEGIN_NAMESPACE -#ifndef QT_NO_FILEDIALOG -typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, - const QString &filter, QString *selectedFilter, QFileDialog::Options options); -typedef QString (*_qt_filedialog_open_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, - const QString &filter, QString *selectedFilter, QFileDialog::Options options); -typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, - const QString &filter, QString *selectedFilter, QFileDialog::Options options); -typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, - QFileDialog::Options options); - -extern Q_WIDGETS_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; -extern Q_WIDGETS_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; -extern Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; -extern Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; -#endif //!QT_NO_FILEDIALOG - class QGtkPainter; class QGtkStylePrivate; @@ -326,20 +293,6 @@ public: static QString getThemeName(); virtual int getSpinboxArrowSize() const; -#ifndef QT_NO_FILEDIALOG - static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, - const QString &dir, const QString &filter, QString *selectedFilter, - QFileDialog::Options options, bool isSaveDialog = false, - QHash *filterMap = 0); - - static QString openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options); - static QString saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options); - static QString openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); - static QStringList openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options); -#endif static QIcon getFilesystemIcon(const QFileInfo &); static Ptr_gtk_container_forall gtk_container_forall; @@ -425,20 +378,6 @@ public: static Ptr_pango_font_description_get_family pango_font_description_get_family; static Ptr_pango_font_description_get_style pango_font_description_get_style; - static Ptr_gtk_file_filter_new gtk_file_filter_new; - static Ptr_gtk_file_filter_set_name gtk_file_filter_set_name; - static Ptr_gtk_file_filter_add_pattern gtk_file_filter_add_pattern; - static Ptr_gtk_file_chooser_add_filter gtk_file_chooser_add_filter; - static Ptr_gtk_file_chooser_set_filter gtk_file_chooser_set_filter; - static Ptr_gtk_file_chooser_get_filter gtk_file_chooser_get_filter; - static Ptr_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new; - static Ptr_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder; - static Ptr_gtk_file_chooser_get_filename gtk_file_chooser_get_filename; - static Ptr_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames; - static Ptr_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name; - static Ptr_gtk_dialog_run gtk_dialog_run; - static Ptr_gtk_file_chooser_set_filename gtk_file_chooser_set_filename; - static Ptr_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels; static Ptr_gdk_pixbuf_get_width gdk_pixbuf_get_width; static Ptr_gdk_pixbuf_get_height gdk_pixbuf_get_height; -- cgit v1.2.3 From 72fe9f1d0df9bf2cb49306aea571a88056591f6d Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Thu, 20 Feb 2014 16:50:15 +0100 Subject: Fix a crash of accessing deleted paintengine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When painting to QPixmap with QBlitterPaintEngine and dfb PaintEngine have PaintDevice (pdev) as QImage. Painter code uses PaintDevice::paintEngine() to refer to paintEngine. This will became dangling pointer since QDirectFbBlitter::doLock() will delete QImage. Instead return QPixmap as PaintDevice. Change-Id: Idfac919b6438a82b412020e441e0a102e4a2a052 Reviewed-by: Jørgen Lind --- src/gui/painting/qpaintengine_blitter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp index e356a3a36a..26eacacd49 100644 --- a/src/gui/painting/qpaintengine_blitter.cpp +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -494,11 +494,12 @@ void QBlitterPaintEngine::clipEnabledChanged() bool QBlitterPaintEngine::begin(QPaintDevice *pdev) { + Q_D(QBlitterPaintEngine); bool ok = QRasterPaintEngine::begin(pdev); #ifdef QT_BLITTER_RASTEROVERLAY - Q_D(QBlitterPaintEngine); d->pmData->unmergeOverlay(); #endif + d->pdev = pdev; return ok; } -- cgit v1.2.3 From ace3b97d4c295d66cbcbfc2af05f7a50e7dab0f6 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 10 Mar 2014 10:35:03 +0100 Subject: Fix deprecated setOption() usage in GLX integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The correct function is setOptions(). Change-Id: Ife9ff75c409c843b4871804fcfd06b9d2a7733d3 Reviewed-by: Jørgen Lind Reviewed-by: Sean Harmer --- src/plugins/platforms/xcb/qglxintegration.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index eaa4d05311..c183deb3b8 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -130,7 +130,7 @@ static void updateFormatFromContext(QSurfaceFormat &format) } format.setProfile(QSurfaceFormat::NoProfile); - format.setOption(QSurfaceFormat::FormatOptions()); + format.setOptions(QSurfaceFormat::FormatOptions()); if (format.renderableType() == QSurfaceFormat::OpenGL) { if (format.version() < qMakePair(3, 0)) { @@ -211,7 +211,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat // Don't bother with versions below ES 2.0 glVersions << 30 << 20; // ES does not support any format option - m_format.setOption(QSurfaceFormat::FormatOptions()); + m_format.setOptions(QSurfaceFormat::FormatOptions()); } Q_ASSERT(glVersions.count() > 0); -- cgit v1.2.3 From 4dcf40b30894c0535f8a06235d01928cd434819d Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 22 Feb 2014 14:06:43 +0200 Subject: Make bundled HarfBuzz-NG not depend on Qt Change-Id: Id2a0e4ae4cf2b4a6c95985b3b31c846aac92f992 Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz-ng/src/config.h | 17 +---------------- src/3rdparty/harfbuzz.pri | 1 - 2 files changed, 1 insertion(+), 17 deletions(-) (limited to 'src') diff --git a/src/3rdparty/harfbuzz-ng/src/config.h b/src/3rdparty/harfbuzz-ng/src/config.h index db706987fe..cb68ab0e5b 100644 --- a/src/3rdparty/harfbuzz-ng/src/config.h +++ b/src/3rdparty/harfbuzz-ng/src/config.h @@ -2,29 +2,14 @@ #define HB_CONFIG_H #define HAVE_OT +#define HAVE_ATEXIT #define HB_NO_MT #define HB_NO_UNICODE_FUNCS #define HB_DISABLE_DEPRECATED -#include - -#ifndef HB_INTERNAL -# define HB_INTERNAL Q_DECL_HIDDEN -#endif - -#if !defined(QT_NO_DEBUG) -# define NDEBUG -#endif - // because strdup() is not part of strict Posix, declare it here extern "C" char *strdup(const char *src); -#ifndef HAVE_ATEXIT -# define HAVE_ATEXIT 1 -# include -# define atexit qAddPostRoutine -#endif - #endif /* HB_CONFIG_H */ diff --git a/src/3rdparty/harfbuzz.pri b/src/3rdparty/harfbuzz.pri index e61ee7eab6..1b7f7b95e1 100644 --- a/src/3rdparty/harfbuzz.pri +++ b/src/3rdparty/harfbuzz.pri @@ -113,7 +113,6 @@ contains(QT_CONFIG, harfbuzz) { } DEFINES += HAVE_CONFIG_H - QT += core-private TR_EXCLUDE += $$QT_HARFBUZZ_DIR/* } else:contains(QT_CONFIG, system-harfbuzz) { -- cgit v1.2.3 From a7e58bf253d08b896df3bbf247bbbaae718e426d Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Tue, 25 Feb 2014 15:33:43 +0200 Subject: Build bundled HarfBuzz-NG outside QtGui Being a part of QtGui, HarfBuzz-NG breaks build with -Werror. Instead of disabling a particular warnings-as-errors, build a prefixed static library and make it a link-time dependency. Change-Id: Id0be1f0e0034092d50f83cd364d5c65940fee869 Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro | 126 +++++++++++++++++++++++++++++++ src/3rdparty/harfbuzz.pri | 120 ----------------------------- src/3rdparty/harfbuzzng.pri | 6 ++ src/gui/text/text.pri | 2 +- src/src.pro | 10 ++- 5 files changed, 142 insertions(+), 122 deletions(-) create mode 100644 src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro delete mode 100644 src/3rdparty/harfbuzz.pri create mode 100644 src/3rdparty/harfbuzzng.pri (limited to 'src') diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro new file mode 100644 index 0000000000..d65520927b --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro @@ -0,0 +1,126 @@ +TARGET = qtharfbuzzng +TEMPLATE = lib + +CONFIG += \ + static \ + hide_symbols \ + exceptions_off rtti_off +CONFIG -= qt + +DESTDIR = $$QT_BUILD_TREE/lib + +DEFINES += HAVE_CONFIG_H +HEADERS += $$PWD/src/config.h + +INCLUDEPATH += $$PWD/include + +SOURCES += \ + $$PWD/src/hb-blob.cc \ + $$PWD/src/hb-buffer.cc \ + $$PWD/src/hb-buffer-serialize.cc \ + $$PWD/src/hb-common.cc \ + $$PWD/src/hb-face.cc \ + $$PWD/src/hb-font.cc \ + $$PWD/src/hb-ot-tag.cc \ + $$PWD/src/hb-set.cc \ + $$PWD/src/hb-shape.cc \ + $$PWD/src/hb-shape-plan.cc \ + $$PWD/src/hb-shaper.cc \ + $$PWD/src/hb-unicode.cc \ + $$PWD/src/hb-warning.cc + +HEADERS += \ + $$PWD/src/hb-atomic-private.hh \ + $$PWD/src/hb-buffer-private.hh \ + $$PWD/src/hb-buffer-deserialize-json.hh \ + $$PWD/src/hb-buffer-deserialize-text.hh \ + $$PWD/src/hb-cache-private.hh \ + $$PWD/src/hb-face-private.hh \ + $$PWD/src/hb-font-private.hh \ + $$PWD/src/hb-mutex-private.hh \ + $$PWD/src/hb-object-private.hh \ + $$PWD/src/hb-open-file-private.hh \ + $$PWD/src/hb-open-type-private.hh \ + $$PWD/src/hb-ot-head-table.hh \ + $$PWD/src/hb-ot-hhea-table.hh \ + $$PWD/src/hb-ot-hmtx-table.hh \ + $$PWD/src/hb-ot-maxp-table.hh \ + $$PWD/src/hb-ot-name-table.hh \ + $$PWD/src/hb-private.hh \ + $$PWD/src/hb-set-private.hh \ + $$PWD/src/hb-shape-plan-private.hh \ + $$PWD/src/hb-shaper-impl-private.hh \ + $$PWD/src/hb-shaper-list.hh \ + $$PWD/src/hb-shaper-private.hh \ + $$PWD/src/hb-unicode-private.hh \ + $$PWD/src/hb-utf-private.hh + +HEADERS += \ + $$PWD/src/hb.h \ + $$PWD/src/hb-blob.h \ + $$PWD/src/hb-buffer.h \ + $$PWD/src/hb-common.h \ + $$PWD/src/hb-face.h \ + $$PWD/src/hb-font.h \ + $$PWD/src/hb-set.h \ + $$PWD/src/hb-shape.h \ + $$PWD/src/hb-shape-plan.h \ + $$PWD/src/hb-unicode.h \ + $$PWD/src/hb-version.h + +# Open Type +SOURCES += \ + $$PWD/src/hb-ot-layout.cc \ + $$PWD/src/hb-ot-map.cc \ + $$PWD/src/hb-ot-shape.cc \ + $$PWD/src/hb-ot-shape-complex-arabic.cc \ + $$PWD/src/hb-ot-shape-complex-default.cc \ + $$PWD/src/hb-ot-shape-complex-hangul.cc \ + $$PWD/src/hb-ot-shape-complex-hebrew.cc \ + $$PWD/src/hb-ot-shape-complex-indic.cc \ + $$PWD/src/hb-ot-shape-complex-indic-table.cc \ + $$PWD/src/hb-ot-shape-complex-myanmar.cc \ + $$PWD/src/hb-ot-shape-complex-sea.cc \ + $$PWD/src/hb-ot-shape-complex-thai.cc \ + $$PWD/src/hb-ot-shape-complex-tibetan.cc \ + $$PWD/src/hb-ot-shape-fallback.cc \ + $$PWD/src/hb-ot-shape-normalize.cc + +HEADERS += \ + $$PWD/src/hb-ot-layout-common-private.hh \ + $$PWD/src/hb-ot-layout-gdef-table.hh \ + $$PWD/src/hb-ot-layout-gpos-table.hh \ + $$PWD/src/hb-ot-layout-gsubgpos-private.hh \ + $$PWD/src/hb-ot-layout-gsub-table.hh \ + $$PWD/src/hb-ot-layout-jstf-table.hh \ + $$PWD/src/hb-ot-layout-private.hh \ + $$PWD/src/hb-ot-map-private.hh \ + $$PWD/src/hb-ot-shape-complex-arabic-fallback.hh \ + $$PWD/src/hb-ot-shape-complex-arabic-table.hh \ + $$PWD/src/hb-ot-shape-complex-indic-machine.hh \ + $$PWD/src/hb-ot-shape-complex-indic-private.hh \ + $$PWD/src/hb-ot-shape-complex-myanmar-machine.hh \ + $$PWD/src/hb-ot-shape-complex-private.hh \ + $$PWD/src/hb-ot-shape-complex-sea-machine.hh \ + $$PWD/src/hb-ot-shape-fallback-private.hh \ + $$PWD/src/hb-ot-shape-normalize-private.hh \ + $$PWD/src/hb-ot-shape-private.hh + +HEADERS += \ + $$PWD/src/hb-ot.h \ + $$PWD/src/hb-ot-layout.h \ + $$PWD/src/hb-ot-shape.h \ + $$PWD/src/hb-ot-tag.h + +mac { + # Apple Advanced Typography + DEFINES += HAVE_CORETEXT + + SOURCES += \ + $$PWD/src/hb-coretext.cc + + HEADERS += \ + $$PWD/src/hb-coretext.h +} + +TARGET = $$TARGET$$qtPlatformTargetSuffix() diff --git a/src/3rdparty/harfbuzz.pri b/src/3rdparty/harfbuzz.pri deleted file mode 100644 index 1b7f7b95e1..0000000000 --- a/src/3rdparty/harfbuzz.pri +++ /dev/null @@ -1,120 +0,0 @@ -contains(QT_CONFIG, harfbuzz) { - QT_HARFBUZZ_DIR = $$QT_SOURCE_TREE/src/3rdparty/harfbuzz-ng - - INCLUDEPATH += $$QT_HARFBUZZ_DIR/include - - SOURCES += \ - $$QT_HARFBUZZ_DIR/src/hb-blob.cc \ - $$QT_HARFBUZZ_DIR/src/hb-buffer.cc \ - $$QT_HARFBUZZ_DIR/src/hb-buffer-serialize.cc \ - $$QT_HARFBUZZ_DIR/src/hb-common.cc \ - $$QT_HARFBUZZ_DIR/src/hb-face.cc \ - $$QT_HARFBUZZ_DIR/src/hb-font.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-tag.cc \ - $$QT_HARFBUZZ_DIR/src/hb-set.cc \ - $$QT_HARFBUZZ_DIR/src/hb-shape.cc \ - $$QT_HARFBUZZ_DIR/src/hb-shape-plan.cc \ - $$QT_HARFBUZZ_DIR/src/hb-shaper.cc \ - $$QT_HARFBUZZ_DIR/src/hb-unicode.cc \ - $$QT_HARFBUZZ_DIR/src/hb-warning.cc - - HEADERS += \ - $$QT_HARFBUZZ_DIR/src/hb-atomic-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-buffer-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-buffer-deserialize-json.hh \ - $$QT_HARFBUZZ_DIR/src/hb-buffer-deserialize-text.hh \ - $$QT_HARFBUZZ_DIR/src/hb-cache-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-face-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-font-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-mutex-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-object-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-open-file-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-open-type-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-head-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-hhea-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-hmtx-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-maxp-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-name-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-set-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-shape-plan-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-shaper-impl-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-shaper-list.hh \ - $$QT_HARFBUZZ_DIR/src/hb-shaper-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-unicode-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-utf-private.hh - - HEADERS += \ - $$QT_HARFBUZZ_DIR/src/hb.h \ - $$QT_HARFBUZZ_DIR/src/hb-blob.h \ - $$QT_HARFBUZZ_DIR/src/hb-buffer.h \ - $$QT_HARFBUZZ_DIR/src/hb-common.h \ - $$QT_HARFBUZZ_DIR/src/hb-face.h \ - $$QT_HARFBUZZ_DIR/src/hb-font.h \ - $$QT_HARFBUZZ_DIR/src/hb-set.h \ - $$QT_HARFBUZZ_DIR/src/hb-shape.h \ - $$QT_HARFBUZZ_DIR/src/hb-shape-plan.h \ - $$QT_HARFBUZZ_DIR/src/hb-unicode.h \ - $$QT_HARFBUZZ_DIR/src/hb-version.h - - # Open Type - SOURCES += \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-map.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-arabic.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-default.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-hangul.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-hebrew.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic-table.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-myanmar.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-sea.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-thai.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-tibetan.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-fallback.cc \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-normalize.cc - - HEADERS += \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-common-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gdef-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gpos-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gsubgpos-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gsub-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-jstf-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-map-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-arabic-fallback.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-arabic-table.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic-machine.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-myanmar-machine.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-sea-machine.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-fallback-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-normalize-private.hh \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape-private.hh - - HEADERS += \ - $$QT_HARFBUZZ_DIR/src/hb-ot.h \ - $$QT_HARFBUZZ_DIR/src/hb-ot-layout.h \ - $$QT_HARFBUZZ_DIR/src/hb-ot-shape.h \ - $$QT_HARFBUZZ_DIR/src/hb-ot-tag.h - - mac { - # Apple Advanced Typography - SOURCES += \ - $$QT_HARFBUZZ_DIR/src/hb-coretext.cc - - HEADERS += \ - $$QT_HARFBUZZ_DIR/src/hb-coretext.h - - DEFINES += HAVE_CORETEXT - } - - DEFINES += HAVE_CONFIG_H - - TR_EXCLUDE += $$QT_HARFBUZZ_DIR/* -} else:contains(QT_CONFIG, system-harfbuzz) { - LIBS_PRIVATE += -lharfbuzz -} diff --git a/src/3rdparty/harfbuzzng.pri b/src/3rdparty/harfbuzzng.pri new file mode 100644 index 0000000000..74433688f6 --- /dev/null +++ b/src/3rdparty/harfbuzzng.pri @@ -0,0 +1,6 @@ +contains(QT_CONFIG, harfbuzz) { + INCLUDEPATH += $$PWD/harfbuzz-ng/include + LIBS_PRIVATE += -L$$QT_BUILD_TREE/lib -lqtharfbuzzng$$qtPlatformTargetSuffix() +} else:contains(QT_CONFIG, system-harfbuzz) { + LIBS_PRIVATE += -lharfbuzz +} diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index 2a0e4eff32..c67769ad48 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -88,7 +88,7 @@ HEADERS += \ contains(QT_CONFIG, harfbuzz)|contains(QT_CONFIG, system-harfbuzz) { DEFINES += QT_ENABLE_HARFBUZZ_NG - include($$PWD/../../3rdparty/harfbuzz.pri) + include($$PWD/../../3rdparty/harfbuzzng.pri) SOURCES += text/qharfbuzzng.cpp HEADERS += text/qharfbuzzng_p.h diff --git a/src/src.pro b/src/src.pro index 114ee5e424..687f2502ab 100644 --- a/src/src.pro +++ b/src/src.pro @@ -80,6 +80,9 @@ src_testlib.subdir = $$PWD/testlib src_testlib.target = sub-testlib src_testlib.depends = src_corelib # src_gui & src_widgets are not build-depends +src_3rdparty_harfbuzzng.subdir = $$PWD/3rdparty/harfbuzz-ng +src_3rdparty_harfbuzzng.target = sub-3rdparty-harfbuzzng + src_angle.subdir = $$PWD/angle src_angle.target = sub-angle angle_d3d11: src_angle.depends = src_corelib @@ -130,6 +133,10 @@ contains(QT_CONFIG, dbus) { } contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent !contains(QT_CONFIG, no-gui) { + contains(QT_CONFIG, harfbuzz) { + SUBDIRS += src_3rdparty_harfbuzzng + src_gui.depends += src_3rdparty_harfbuzzng + } win32:contains(QT_CONFIG, angle)|contains(QT_CONFIG, dynamicgl) { SUBDIRS += src_angle src_gui.depends += src_angle @@ -159,7 +166,8 @@ android:!android-no-sdk: SUBDIRS += src_android TR_EXCLUDE = \ src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_tools_qlalr \ - src_tools_bootstrap_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml + src_tools_bootstrap_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml \ + src_3rdparty_harfbuzzng sub-tools.depends = $$TOOLS QMAKE_EXTRA_TARGETS = sub-tools -- cgit v1.2.3 From 2e49b7a3b99a0f02c2521656fa2f573c2ea40150 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Wed, 19 Feb 2014 11:01:00 +0100 Subject: BB select(): move special select method to qcore_unix_p.h ... and make it independent of QProcess, because we want to use it from QtNetwork as well. In addition, move select_msecs() to qcore_unix_p.h as well and rename it to qt_select_msecs(). Task-number: QTBUG-36144 Change-Id: Ief681b6f6c80e85aa5091a5a04bcedb60f353217 Reviewed-by: Oswald Buddenhagen Reviewed-by: Rafael Roquetto Reviewed-by: Thiago Macieira --- src/corelib/io/qprocess_p.h | 5 +++ src/corelib/io/qprocess_unix.cpp | 85 ++++++++++++++------------------------- src/corelib/kernel/qcore_unix.cpp | 43 ++++++++++++++++++++ src/corelib/kernel/qcore_unix_p.h | 8 ++++ 4 files changed, 87 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 219bdf8200..5d65b2a068 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -390,6 +390,11 @@ public: qint64 writeToStdin(const char *data, qint64 maxlen); void cleanup(); + +#ifdef Q_OS_BLACKBERRY + QList defaultNotifiers() const; +#endif // Q_OS_BLACKBERRY + #ifdef Q_OS_UNIX static void initializeProcessManager(); #endif diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 0e917ef438..8674371baa 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1042,17 +1042,6 @@ void QProcessPrivate::killProcess() ::kill(pid_t(pid), SIGKILL); } -static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) -{ - if (timeout < 0) - return qt_safe_select(nfds, fdread, fdwrite, 0, 0); - - struct timespec tv; - tv.tv_sec = timeout / 1000; - tv.tv_nsec = (timeout % 1000) * 1000 * 1000; - return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); -} - /* Returns the difference between msecs and elapsed. If msecs is -1, however, -1 is returned. @@ -1066,41 +1055,6 @@ static int qt_timeout_value(int msecs, int elapsed) return timeout < 0 ? 0 : timeout; } -#ifdef Q_OS_BLACKBERRY -// The BlackBerry event dispatcher uses bps_get_event. Unfortunately, already registered -// socket notifiers are disabled by a call to select. This is to rearm the standard streams. -static int bb_select(QProcessPrivate *process, int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) -{ - bool stdoutEnabled = false; - bool stderrEnabled = false; - bool stdinEnabled = false; - - if (process->stdoutChannel.notifier && process->stdoutChannel.notifier->isEnabled()) { - stdoutEnabled = true; - process->stdoutChannel.notifier->setEnabled(false); - } - if (process->stderrChannel.notifier && process->stderrChannel.notifier->isEnabled()) { - stderrEnabled = true; - process->stderrChannel.notifier->setEnabled(false); - } - if (process->stdinChannel.notifier && process->stdinChannel.notifier->isEnabled()) { - stdinEnabled = true; - process->stdinChannel.notifier->setEnabled(false); - } - - const int ret = select_msecs(nfds, fdread, fdwrite, timeout); - - if (stdoutEnabled) - process->stdoutChannel.notifier->setEnabled(true); - if (stderrEnabled) - process->stderrChannel.notifier->setEnabled(true); - if (stdinEnabled) - process->stdinChannel.notifier->setEnabled(true); - - return ret; -} -#endif // Q_OS_BLACKBERRY - bool QProcessPrivate::waitForStarted(int msecs) { Q_Q(QProcess); @@ -1113,7 +1067,7 @@ bool QProcessPrivate::waitForStarted(int msecs) fd_set fds; FD_ZERO(&fds); FD_SET(childStartedPipe[0], &fds); - if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) { + if (qt_select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) { processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); #if defined (QPROCESS_DEBUG) @@ -1129,6 +1083,17 @@ bool QProcessPrivate::waitForStarted(int msecs) return startedEmitted; } +#ifdef Q_OS_BLACKBERRY +QList QProcessPrivate::defaultNotifiers() const +{ + QList notifiers; + notifiers << stdoutChannel.notifier + << stderrChannel.notifier + << stdinChannel.notifier; + return notifiers; +} +#endif // Q_OS_BLACKBERRY + bool QProcessPrivate::waitForReadyRead(int msecs) { Q_Q(QProcess); @@ -1139,6 +1104,10 @@ bool QProcessPrivate::waitForReadyRead(int msecs) QElapsedTimer stopWatch; stopWatch.start(); +#ifdef Q_OS_BLACKBERRY + QList notifiers = defaultNotifiers(); +#endif + forever { fd_set fdread; fd_set fdwrite; @@ -1162,9 +1131,9 @@ bool QProcessPrivate::waitForReadyRead(int msecs) int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); #ifdef Q_OS_BLACKBERRY - int ret = bb_select(this, nfds + 1, &fdread, &fdwrite, timeout); + int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout); #else - int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); + int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout); #endif if (ret < 0) { break; @@ -1215,6 +1184,10 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) QElapsedTimer stopWatch; stopWatch.start(); +#ifdef Q_OS_BLACKBERRY + QList notifiers = defaultNotifiers(); +#endif + while (!writeBuffer.isEmpty()) { fd_set fdread; fd_set fdwrite; @@ -1239,9 +1212,9 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); #ifdef Q_OS_BLACKBERRY - int ret = bb_select(this, nfds + 1, &fdread, &fdwrite, timeout); + int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout); #else - int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); + int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout); #endif if (ret < 0) { break; @@ -1286,6 +1259,10 @@ bool QProcessPrivate::waitForFinished(int msecs) QElapsedTimer stopWatch; stopWatch.start(); +#ifdef Q_OS_BLACKBERRY + QList notifiers = defaultNotifiers(); +#endif + forever { fd_set fdread; fd_set fdwrite; @@ -1310,9 +1287,9 @@ bool QProcessPrivate::waitForFinished(int msecs) int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); #ifdef Q_OS_BLACKBERRY - int ret = bb_select(this, nfds + 1, &fdread, &fdwrite, timeout); + int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout); #else - int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); + int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout); #endif if (ret < 0) { break; @@ -1349,7 +1326,7 @@ bool QProcessPrivate::waitForWrite(int msecs) fd_set fdwrite; FD_ZERO(&fdwrite); FD_SET(stdinChannel.pipe[1], &fdwrite); - return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; + return qt_select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; } void QProcessPrivate::findExitCode() diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index e4181b5c86..8d788419fb 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -58,6 +58,10 @@ #include #endif +#ifdef Q_OS_BLACKBERRY +#include +#endif // Q_OS_BLACKBERRY + QT_BEGIN_NAMESPACE static inline bool time_update(struct timespec *tv, const struct timespec &start, @@ -106,4 +110,43 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, } } +int qt_select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) +{ + if (timeout < 0) + return qt_safe_select(nfds, fdread, fdwrite, 0, 0); + + struct timespec tv; + tv.tv_sec = timeout / 1000; + tv.tv_nsec = (timeout % 1000) * 1000 * 1000; + return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); +} + +#ifdef Q_OS_BLACKBERRY +// The BlackBerry event dispatcher uses bps_get_event. Unfortunately, already registered +// socket notifiers are disabled by a call to select. This is to rearm the standard streams. +int bb_select(QList socketNotifiers, int nfds, fd_set *fdread, fd_set *fdwrite, + int timeout) +{ + QList socketNotifiersEnabled; + socketNotifiersEnabled.reserve(socketNotifiers.count()); + for (int a = 0; a < socketNotifiers.count(); ++a) { + if (socketNotifiers.at(a) && socketNotifiers.at(a)->isEnabled()) { + socketNotifiersEnabled[a] = true; + socketNotifiers.at(a)->setEnabled(false); + } else { + socketNotifiersEnabled[a] = false; + } + } + + const int ret = qt_select_msecs(nfds, fdread, fdwrite, timeout); + + for (int a = 0; a < socketNotifiers.count(); ++a) { + if (socketNotifiersEnabled.at(a) == true) + socketNotifiers.at(a)->setEnabled(true); + } + + return ret; +} +#endif // Q_OS_BLACKBERRY + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 7ab632d7a0..df78ef6692 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -343,6 +343,14 @@ void qt_nanosleep(timespec amount); Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timespec *tv); +int qt_select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout); + +#ifdef Q_OS_BLACKBERRY +class QSocketNotifier; +Q_CORE_EXPORT int bb_select(QList socketNotifiers, int nfds, fd_set *fdread, + fd_set *fdwrite, int timeout); +#endif // Q_OS_BLACKBERRY + // according to X/OPEN we have to define semun ourselves // we use prefix as on some systems sem.h will have it struct semid_ds; -- cgit v1.2.3 From 6d05f5faff8b125c3e43192b857990e7f0ff208d Mon Sep 17 00:00:00 2001 From: Alejandro Exojo Date: Fri, 7 Mar 2014 12:20:30 +0100 Subject: Make QtCriticalMsg exit on QT_FATAL_CRITICALS Change-Id: I92e8f9851dd074f3bcded6981f5545d1e93b549f Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira Reviewed-by: Kai Koehne --- src/corelib/global/qglobal.cpp | 2 ++ src/corelib/global/qlogging.cpp | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 108866b8df..66664f0f2a 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -3291,6 +3291,8 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) stderr. Under Windows, the message is sent to the debugger. On Blackberry the message is sent to slogger2. + It exits if the environment variable QT_FATAL_CRITICALS is not empty. + This function takes a format string and a list of arguments, similar to the C printf() function. The format should be a Latin-1 string. diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 64dd544cf0..d8ef8a57a8 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -83,6 +83,11 @@ static bool isFatal(QtMsgType msgType) if (msgType == QtFatalMsg) return true; + if (msgType == QtCriticalMsg) { + static bool fatalCriticals = !qEnvironmentVariableIsEmpty("QT_FATAL_CRITICALS"); + return fatalCriticals; + } + if (msgType == QtWarningMsg || msgType == QtCriticalMsg) { static bool fatalWarnings = !qEnvironmentVariableIsEmpty("QT_FATAL_WARNINGS"); return fatalWarnings; -- cgit v1.2.3 From cbf5aa625d1a41156880cccbe081e84fc0c1067e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 11 Mar 2014 15:39:38 +0100 Subject: Windows: Change defaultNameFilterDisables() to return false. As was done in Qt 4, where QFileDialog sets NameFilterDisables() to true for Q_WS_MAC only. Task-number: QTBUG-37302 Change-Id: I162f9e79762aa4fa68aba02d1bdfc6322d472a9d Reviewed-by: Shawn Rutledge --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index b6ff3dc3ce..0951009cf0 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1559,7 +1559,7 @@ public: QWindowsFileDialogHelper() {} virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; } virtual bool defaultNameFilterDisables() const - { return true; } + { return false; } virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; virtual QUrl directory() const Q_DECL_OVERRIDE; virtual void selectFile(const QUrl &filename) Q_DECL_OVERRIDE; -- cgit v1.2.3 From 6d858a0fdb896d2c4f9f6411f691f0648c084cd7 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Thu, 5 Dec 2013 17:33:24 +0100 Subject: XCB plugin: query screen resources without _current xcb_randr_get_screen_resources() and xcb_randr_get_screen_resources_current() do basically the same, but for one case: if nothing has queried these information ever before. So if an application is the very first client ever to connect to an X server it may just return nothing. A call to xcb_randr_get_screen_info_reply() will then cause the X server to allocate the needed information and send an update notification, resulting in a second QXcbScreen being created, but the other one is still around and probably used. The behavior I observed with a simple test application was that the application was not visible on the screen when it was the first client ever on the X server. Killing the application and starting it again made it work just fine. Change-Id: Id64f267e8ebcfa5b39d21d98307170a09e5169df Reviewed-by: Uli Schlachter Reviewed-by: Gatis Paeglis Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 030090d98d..a68ae8cf71 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -144,23 +144,23 @@ void QXcbConnection::updateScreens() xcb_generic_error_t *error = NULL; xcb_randr_get_output_primary_cookie_t primaryCookie = xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); - xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root); + xcb_randr_get_screen_resources_cookie_t resourcesCookie = + xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); xcb_randr_get_output_primary_reply_t *primary = xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error); if (!primary || error) { qWarning("QXcbConnection: Failed to get the primary output of the screen"); free(error); } else { - xcb_randr_get_screen_resources_current_reply_t *resources = - xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error); + xcb_randr_get_screen_resources_reply_t *resources = + xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error); if (!resources || error) { qWarning("QXcbConnection: Failed to get the screen resources"); free(error); } else { xcb_timestamp_t timestamp = resources->config_timestamp; - outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources); - xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(resources); + outputCount = xcb_randr_get_screen_resources_outputs_length(resources); + xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources); for (int i = 0; i < outputCount; i++) { xcb_randr_get_output_info_reply_t *output = -- cgit v1.2.3 From d9c34e9cdd24937a3c487d0f525a8b8b38ee1ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 26 Aug 2013 10:49:48 +0200 Subject: Repaint widgets on screen change. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a screenChanged handler slot to QWidgetWindow, which calls markDirty() on the backing store with the BufferInvalid and UpdateNow flags set. Update CocoaBackingStore to create a new buffer on window devicePixelRatio change. Use the QCocoaWindow::devicePixelRatio() implementation instead of a duplicate implementation in the backing store. The plan is to replace this implementation with one based on QUpdateWindowRequestEvent for Qt 5.4 Change-Id: I8e521c53df4ac90815613e730fe821996334721f Reviewed-by: Jørgen Lind --- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 23 +++++++++-------------- src/widgets/kernel/qwidgetwindow.cpp | 14 ++++++++++++++ src/widgets/kernel/qwidgetwindow_qpa_p.h | 1 + 3 files changed, 24 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 3ca611b537..2222b51a42 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -59,25 +59,20 @@ QCocoaBackingStore::~QCocoaBackingStore() QPaintDevice *QCocoaBackingStore::paintDevice() { - if (m_qImage.size() / m_qImage.devicePixelRatio() != m_requestedSize) { + QCocoaWindow *cocoaWindow = static_cast(window()->handle()); + int windowDevicePixelRatio = int(cocoaWindow->devicePixelRatio()); + + // Receate the backing store buffer if the effective buffer size has changed, + // either due to a window resize or devicePixelRatio change. + QSize effectiveBufferSize = m_requestedSize * windowDevicePixelRatio; + if (m_qImage.size() != effectiveBufferSize) { CGImageRelease(m_cgImage); m_cgImage = 0; - int scaleFactor = 1; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - QCocoaWindow *cocoaWindow = static_cast(window()->handle()); - if (cocoaWindow && cocoaWindow->m_contentView && [cocoaWindow->m_contentView window]) { - scaleFactor = int([[cocoaWindow->m_contentView window] backingScaleFactor]); - } - } -#endif - - QCocoaWindow *cocoaWindow = static_cast(window()->handle()); QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - m_qImage = QImage(m_requestedSize * scaleFactor, format); - m_qImage.setDevicePixelRatio(scaleFactor); + m_qImage = QImage(effectiveBufferSize, format); + m_qImage.setDevicePixelRatio(windowDevicePixelRatio); if (format == QImage::Format_ARGB32_Premultiplied) m_qImage.fill(Qt::transparent); } diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index e50736d6b8..ef138267bb 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -100,6 +100,7 @@ QWidgetWindow::QWidgetWindow(QWidget *widget) setSurfaceType(QSurface::RasterGLSurface); } connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); + connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(repaintWindow())); } QWidgetWindow::~QWidgetWindow() @@ -560,6 +561,19 @@ void QWidgetWindow::updateGeometry() m_widget->data->fstrut_dirty = false; } +// Invalidates the backing store buffer and repaints immediately. +// ### Qt 5.4: replace with QUpdateWindowRequestEvent. +void QWidgetWindow::repaintWindow() +{ + if (!m_widget->isVisible() || !m_widget->updatesEnabled()) + return; + + QTLWExtra *tlwExtra = m_widget->window()->d_func()->maybeTopData(); + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) + tlwExtra->backingStoreTracker->markDirty(m_widget->rect(), m_widget, + QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid); +} + Qt::WindowState effectiveState(Qt::WindowStates state); // Store normal geometry used for saving application settings. diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h index 8d6f14a669..06ba8ea646 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa_p.h +++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h @@ -101,6 +101,7 @@ protected: private slots: void updateObjectName(); + void repaintWindow(); private: void updateGeometry(); -- cgit v1.2.3 From 0a24d653b608886897ba8c54ab18cec97bf09404 Mon Sep 17 00:00:00 2001 From: Risto Avila Date: Mon, 3 Mar 2014 14:16:57 +0200 Subject: Fix Direct2D clipping when Qt::WA_OpaquePaintEvent is true Changed clip rectangle handling from bounding rect to region. Now also sub region rectangles are taken in to account. Task-number: QTBUG-37199 Change-Id: I9e09376e2c6d3fee8f85db753295a6138a03096f Reviewed-by: Friedemann Kleint Reviewed-by: Janne Koskinen Reviewed-by: Louai Al-Khanji Reviewed-by: Andrew Knight --- .../direct2d/qwindowsdirect2dpaintengine.cpp | 51 +++++++++++++++++----- 1 file changed, 40 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index e19a6be47b..d8f34fc3ed 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -77,6 +77,12 @@ enum { D2DDebugDrawStaticTextItemTag, D2DDebugDrawTextItemTag }; + +//Clipping flags +enum { + UserClip = 0x1, + SimpleSystemClip = 0x2 +}; #define D2D_TAG(tag) d->dc()->SetTags(tag, tag) Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); @@ -286,7 +292,7 @@ class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate public: QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm) : bitmap(bm) - , clipPushed(false) + , clipFlags(0) { pen.reset(); brush.reset(); @@ -297,7 +303,7 @@ public: QWindowsDirect2DBitmap *bitmap; QPainterPath clipPath; - bool clipPushed; + unsigned int clipFlags; QPointF currentBrushOrigin; @@ -381,14 +387,14 @@ public: NULL, D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND), NULL); - clipPushed = true; + clipFlags |= UserClip; } void popClip() { - if (clipPushed) { + if (clipFlags & UserClip) { dc()->PopLayer(); - clipPushed = false; + clipFlags &= ~UserClip; } } @@ -397,7 +403,7 @@ public: Q_Q(const QWindowsDirect2DPaintEngine); if (!q->state()->clipEnabled) popClip(); - else if (!clipPushed) + else if (!(clipFlags & UserClip)) pushClip(); } @@ -729,11 +735,29 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev) d->bitmap->deviceContext()->begin(); d->dc()->SetTransform(D2D1::Matrix3x2F::Identity()); - QRect clip(0, 0, pdev->width(), pdev->height()); - if (!systemClip().isEmpty()) - clip &= systemClip().boundingRect(); + if (systemClip().rectCount() > 1) { + QPainterPath p; + p.addRegion(systemClip()); - d->dc()->PushAxisAlignedClip(to_d2d_rect_f(clip), D2D1_ANTIALIAS_MODE_ALIASED); + ComPtr geometry = painterPathToPathGeometry(p); + if (!geometry) + return false; + + d->dc()->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), + geometry.Get(), + d->antialiasMode(), + D2D1::IdentityMatrix(), + 1.0, + NULL, + D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND), + NULL); + } else { + QRect clip(0, 0, pdev->width(), pdev->height()); + if (!systemClip().isEmpty()) + clip &= systemClip().boundingRect(); + d->dc()->PushAxisAlignedClip(to_d2d_rect_f(clip), D2D1_ANTIALIAS_MODE_ALIASED); + d->clipFlags |= SimpleSystemClip; + } D2D_TAG(D2DDebugDrawInitialStateTag); @@ -746,7 +770,12 @@ bool QWindowsDirect2DPaintEngine::end() // First pop any user-applied clipping d->popClip(); // Now the system clip from begin() above - d->dc()->PopAxisAlignedClip(); + if (d->clipFlags & SimpleSystemClip) { + d->dc()->PopAxisAlignedClip(); + d->clipFlags &= ~SimpleSystemClip; + } else { + d->dc()->PopLayer(); + } return d->bitmap->deviceContext()->end(); } -- cgit v1.2.3 From ecb7fd9ff76d13ebffbc79c67aee38efe562a482 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 10 Mar 2014 13:34:48 +0100 Subject: [XCB] Fix drag-and-drop segfault QXcbDrag inherits QBasicDrag which takes care of calling updateAction() when needed, we don't need to call it explicitly. Task-number: QTBUG-33057 Change-Id: I754408f74f56de36ace8ffa40a61bd7c64619899 Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbdrag.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 61dfe8ac17..e931b96b88 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -872,7 +872,6 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event) } QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction); - updateAction(Qt::IgnoreAction); xdnd_dragsource = 0; xdnd_types.clear(); -- cgit v1.2.3 From 2954d51579755ea76292f50b4f6d5cd010050fb4 Mon Sep 17 00:00:00 2001 From: Marcel Krems Date: Tue, 11 Mar 2014 20:34:41 +0100 Subject: Add compiler name for Clang in QLibraryInfo::build() Change-Id: I88490f01edc00f5d3c9570fa630915a11c843311 Reviewed-by: Friedemann Kleint --- src/corelib/global/qlibraryinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 689de48e26..39bfd339c3 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -257,9 +257,9 @@ QLibraryInfo::buildDate() #if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too # ifdef __apple_build_version__ // Apple clang has other version numbers -# define COMPILER_STRING __clang_version__ " (Apple)" +# define COMPILER_STRING "Clang " __clang_version__ " (Apple)" # else -# define COMPILER_STRING __clang_version__ +# define COMPILER_STRING "Clang " __clang_version__ # endif #elif defined(Q_CC_GNU) # define COMPILER_STRING "GCC " __VERSION__ -- cgit v1.2.3 From b14e4eb5f0a74e00be678c82d9e552b9e26ad91f Mon Sep 17 00:00:00 2001 From: Marcel Krems Date: Tue, 11 Mar 2014 21:10:26 +0100 Subject: Add missing \since 5.0 to QProcess::{program,arguments}. Change-Id: Ie2ce1860e1c63c0955b0a2bee7f8b33c91b9f628 Reviewed-by: Christian Kandeler --- src/corelib/io/qprocess.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 3b78351809..d728bcce94 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2227,6 +2227,8 @@ void QProcess::start(const QString &command, OpenMode mode) } /*! + \since 5.0 + Returns the program the process was last started with. \sa start() @@ -2256,6 +2258,8 @@ void QProcess::setProgram(const QString &program) } /*! + \since 5.0 + Returns the command line arguments the process was last started with. \sa start() -- cgit v1.2.3 From df757e30f816bee8bed5f65ff8e63cec57fe46b1 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 12 Mar 2014 14:07:44 +0100 Subject: Fix compilation with QNATIVESOCKETENGINE_DEBUG enabled Change-Id: Ie60b70aaa1fe11de613ba99427be00e307b6769d Reviewed-by: Peter Hartmann --- src/network/socket/qnativesocketengine_unix.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index b6035b5500..b1b19528c2 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -363,7 +363,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) { #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); + qDebug("QNativeSocketEnginePrivate::nativeConnect() : %lli", socketDescriptor); #endif struct sockaddr_in sockAddrIPv4; @@ -847,7 +847,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %i", recvResult); + qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult); #endif return qint64(recvResult); @@ -1012,13 +1012,13 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() socketType = QAbstractSocket::UnknownSocketType; } #if defined (QNATIVESOCKETENGINE_DEBUG) - QString socketProtocolStr = "UnknownProtocol"; - if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol"; - else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol"; + QString socketProtocolStr = QStringLiteral("UnknownProtocol"); + if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral("IPv4Protocol"); + else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = QStringLiteral("IPv6Protocol"); - QString socketTypeStr = "UnknownSocketType"; - if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket"; - else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket"; + QString socketTypeStr = QStringLiteral("UnknownSocketType"); + if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral("TcpSocket"); + else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral("UdpSocket"); qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i," " peer == %s:%i, socket == %s - %s", @@ -1112,7 +1112,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", + qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %zd", data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), maxSize, r); #endif -- cgit v1.2.3 From 530f9856519e58c7793095a5ac92d49b192d3b0b Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 12 Mar 2014 15:50:36 +0100 Subject: [XCB] Fix crash in QML drag-and-drop Use QPointer to make sure that we are not trying to destroy already deleted object. Task-number: QTBUG-35702 Change-Id: Ib746996787488e636f25e6ea5be0571607ee2ded Reviewed-by: Laszlo Agocs Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbdrag.cpp | 3 ++- src/plugins/platforms/xcb/qxcbdrag.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index e931b96b88..4f0f57c375 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1044,7 +1044,8 @@ void QXcbDrag::timerEvent(QTimerEvent* e) - showing dialog box on drop event where user's response takes more time than XdndDropTransactionTimeout (QTBUG-14493) - dnd takes unusually long time to process data */ - t.drag->deleteLater(); + if (t.drag) + t.drag->deleteLater(); transactions.removeAt(i--); } else { stopTimer = false; diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 5648f70d9e..d94c42696f 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -157,7 +157,7 @@ private: xcb_window_t proxy_target; QWindow *targetWindow; // QWidget *embedding_widget; - QDrag *drag; + QPointer drag; QTime time; }; QList transactions; -- cgit v1.2.3 From ff7f3aba39e69465caeea2f6fff0f41ec86fdb44 Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Wed, 12 Mar 2014 11:44:21 -0400 Subject: Complete support for no-fullscreen parameter Change the code so that it doesn't force application windows to full screen when the no-fullscreen parameter is used in the QT_QPA_PLATFORM environment variable. Task-number: QTBUG-37456 Change-Id: If9612cc2ca69f829d45e7fd4b83338c3a41cf986 Reviewed-by: Kevin Krammer Reviewed-by: Fabian Bumberger --- src/plugins/platforms/qnx/qqnxeglwindow.cpp | 5 ++--- src/plugins/platforms/qnx/qqnxwindow.cpp | 9 +++++++-- src/plugins/platforms/qnx/qqnxwindow.h | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp index 3c08cc9f82..f1f9f5469c 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp @@ -70,8 +70,7 @@ QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool nee if (result != 0) qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno); - m_requestedBufferSize = screen()->rootWindow() == this ? - screen()->geometry().size() : window->geometry().size(); + m_requestedBufferSize = shouldMakeFullScreen() ? screen()->geometry().size() : window->geometry().size(); } QQnxEglWindow::~QQnxEglWindow() @@ -156,7 +155,7 @@ EGLSurface QQnxEglWindow::getSurface() void QQnxEglWindow::setGeometry(const QRect &rect) { //If this is the root window, it has to be shown fullscreen - const QRect &newGeometry = screen()->rootWindow() == this ? screen()->geometry() : rect; + const QRect &newGeometry = shouldMakeFullScreen() ? screen()->geometry() : rect; //We need to request that the GL context updates // the EGLsurface on which it is rendering. diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 9ae2d01ab4..e43aaa83e8 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -242,7 +242,7 @@ QQnxWindow::~QQnxWindow() void QQnxWindow::setGeometry(const QRect &rect) { QRect newGeometry = rect; - if (screen()->rootWindow() == this) //If this is the root window, it has to be shown fullscreen + if (shouldMakeFullScreen()) newGeometry = screen()->geometry(); setGeometryHelper(newGeometry); @@ -714,7 +714,7 @@ void QQnxWindow::initWindow() if (window()->parent() && window()->parent()->handle()) setParent(window()->parent()->handle()); - if (screen()->rootWindow() == this) { + if (shouldMakeFullScreen()) { setGeometryHelper(screen()->geometry()); QWindowSystemInterface::handleGeometryChange(window(), screen()->geometry()); } else { @@ -817,4 +817,9 @@ void QQnxWindow::windowPosted() qqnxLgmonFramePosted(m_cover); // for performance measurements } +bool QQnxWindow::shouldMakeFullScreen() const +{ + return ((screen()->rootWindow() == this) && (QQnxIntegration::options() & QQnxIntegration::FullScreenApplication)); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index e97e941a08..9a2006396f 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -112,6 +112,8 @@ public: QByteArray groupName() const { return m_windowGroupName; } void joinWindowGroup(const QByteArray &groupName); + bool shouldMakeFullScreen() const; + protected: virtual int pixelFormat() const = 0; virtual void resetBuffers() = 0; -- cgit v1.2.3 From 9cd2dac348f45c4b93f74f8ebe20d7528821f003 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 12 Mar 2014 17:49:50 +0100 Subject: Vista Style: More menu item pixel fixes for QtQuick Controls Includes a one-pixel fix for widgets, where the menu item text would be one pixel too far away from the vertical gutter. Task-number: QTBUG-37451 Change-Id: I2539233814a427c5bed66a5c07584717eb3df418 Reviewed-by: Jens Bache-Wiig Reviewed-by: Mitch Curtis --- src/widgets/styles/qwindowsvistastyle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 3d77e39ce8..6955ec83e0 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -1273,7 +1273,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QPoint p1 = QPoint(x + checkcol, yoff); QPoint p2 = QPoint(x + w + 6 , yoff); stateId = MBI_HOT; - QRect subRect(p1.x(), p1.y(), p2.x() - p1.x(), 6); + QRect subRect(p1.x() + (3 - menuitem->rect.x()), p1.y(), p2.x() - p1.x(), 6); subRect = QStyle::visualRect(option->direction, option->rect, subRect ); XPThemeData theme2(widget, painter, QWindowsXPStylePrivate::MenuTheme, @@ -1348,7 +1348,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (dis) painter->setPen(textColor); - int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xm = windowsItemFrame + checkcol + windowsItemHMargin + (3 - menuitem->rect.x()) - 1; int xpos = menuitem->rect.x() + xm; QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect); -- cgit v1.2.3 From fde6450b598a047ec22e495837cf892049ed7add Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Thu, 13 Mar 2014 11:51:03 +0100 Subject: Add workaround for bug in the Mesa glsl optimizer Change-Id: I23251f5288b41f5b7f86406984fdd854127797a9 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopengltextureblitter.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp index d52517add2..9710f1677c 100644 --- a/src/gui/opengl/qopengltextureblitter.cpp +++ b/src/gui/opengl/qopengltextureblitter.cpp @@ -68,11 +68,8 @@ static const char fragment_shader150[] = "uniform sampler2D textureSampler;" "uniform bool swizzle;" "void main() {" - " if (swizzle) {" - " fragcolor = texture(textureSampler, uv).bgra;" - " } else {" - " fragcolor = texture(textureSampler,uv);" - " }" + " vec4 tmpFragColor = texture(textureSampler, uv);" + " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;" "}"; static const char vertex_shader[] = @@ -91,11 +88,8 @@ static const char fragment_shader[] = "uniform sampler2D textureSampler;" "uniform bool swizzle;" "void main() {" - " if (swizzle) {" - " gl_FragColor = texture2D(textureSampler, uv).bgra;" - " } else {" - " gl_FragColor = texture2D(textureSampler,uv);" - " }" + " highp vec4 tmpFragColor = texture2D(textureSampler,uv);" + " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;" "}"; static const GLfloat vertex_buffer_data[] = { -- cgit v1.2.3 From 08ba111719c8c4809e80e1dc8a1956dcfdd9d80d Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Thu, 13 Mar 2014 15:11:22 +0100 Subject: Don't block Key_Back in file dialog Update the 10 year old FIXME hack to allow Key_Back (which will close the dialog on Android). Also clean up nearby code that has been dead for seven years. Task-number: QTBUG-35784 Change-Id: I609858afb2caefe7025e421406288ae56717fea5 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/widgets/dialogs/qfiledialog.cpp | 7 +------ src/widgets/dialogs/qfiledialog_p.h | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 3e4490e890..bea92e9f84 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3904,13 +3904,8 @@ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e) int key = e->key(); QLineEdit::keyPressEvent(e); - if (key != Qt::Key_Escape) + if (key != Qt::Key_Escape && key != Qt::Key_Back) e->accept(); - if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) { - e->accept(); - hide(); - d_ptr->currentView()->setFocus(Qt::ShortcutFocusReason); - } } #ifndef QT_NO_FSCOMPLETER diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index faa721572c..632bbca5a4 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -286,7 +286,7 @@ private: class QFileDialogLineEdit : public QLineEdit { public: - QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), hideOnEsc(false), d_ptr(0){} + QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), d_ptr(0){} void setFileDialogPrivate(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; } void keyPressEvent(QKeyEvent *e); bool hideOnEsc; -- cgit v1.2.3 From 1567699c0e5681b577ab203274181105d226116c Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Thu, 13 Mar 2014 15:01:46 +0100 Subject: Handle key release events correctly Properly ignore key events that we don't actually handle. Task-number: QTBUG-35784 Change-Id: Ibd3e72c76367a1dc3b1f2d39538fcf8441082ff2 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/widgets/widgets/qcombobox.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 17a6ededfe..e0f5ac1050 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -3057,6 +3057,8 @@ void QComboBox::keyReleaseEvent(QKeyEvent *e) Q_D(QComboBox); if (d->lineEdit) d->lineEdit->event(e); + else + QWidget::keyReleaseEvent(e); } /*! -- cgit v1.2.3 From 80d4a19f514f66c4ef2c8b5aa40039fdb6b8dd53 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 12 Mar 2014 15:34:49 +0100 Subject: Android: Use proper empty strings in key events A key event with no unicode would get a text of "\0" instead of the empty string. This would lead to various widgets interpreting the Key_Back event as text input, meaning that it would be grabbed by the widget instead of being propagated. Task-number: QTBUG-35784 Change-Id: Ibdb0e491572e41dd1aaf3b03ae1a780731f0559a Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/android/androidjniinput.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 55d44b7377..9d605c7a17 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -517,6 +517,12 @@ namespace QtAndroidInput } } + // maps 0 to the empty string, and anything else to a single-character string + static inline QString toString(jint unicode) + { + return unicode ? QString(QChar(unicode)) : QString(); + } + static void keyDown(JNIEnv */*env*/, jobject /*thiz*/, jint key, jint unicode, jint modifier) { Qt::KeyboardModifiers modifiers; @@ -533,7 +539,7 @@ namespace QtAndroidInput QEvent::KeyPress, mapAndroidKey(key), modifiers, - QChar(unicode), + toString(unicode), false); } @@ -553,7 +559,7 @@ namespace QtAndroidInput QEvent::KeyRelease, mapAndroidKey(key), modifiers, - QChar(unicode), + toString(unicode), false); } -- cgit v1.2.3 From 2aee54c7383f2ceeb0c9b0073464a404df648516 Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Thu, 13 Mar 2014 17:19:31 +0100 Subject: BlackBerry: Add button color to dark palette Change-Id: I35191841e4d606042375ab8af442a339d6a701dd Reviewed-by: Fabian Bumberger --- src/plugins/platforms/qnx/qblackberrytheme.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qblackberrytheme.cpp b/src/plugins/platforms/qnx/qblackberrytheme.cpp index a0f334d909..46ab4d7033 100644 --- a/src/plugins/platforms/qnx/qblackberrytheme.cpp +++ b/src/plugins/platforms/qnx/qblackberrytheme.cpp @@ -60,9 +60,11 @@ QBlackberryTheme::QBlackberryTheme(const QQnxIntegration *integration) : m_integ m_defaultPalette.setBrush(QPalette::Disabled, QPalette::WindowText, color); m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Text, color); - m_defaultPalette.setColor(QPalette::Window, QColor(18, 18, 18)); - m_defaultPalette.setColor(QPalette::Base, QColor(18, 18, 18)); + color.setRgb(18, 18, 18); + m_defaultPalette.setColor(QPalette::Window, color); + m_defaultPalette.setColor(QPalette::Base, color); m_defaultPalette.setColor(QPalette::AlternateBase, QColor(50, 50, 50)); + m_defaultPalette.setColor(QPalette::Button, color); m_defaultPalette.setBrush(QPalette::Highlight, QColor(0, 168, 223)); m_defaultPalette.setBrush(QPalette::HighlightedText, QColor(250, 250,250)); -- cgit v1.2.3 From 02abe7921bd84bccfe68a40923f00f48512f0d53 Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Thu, 13 Mar 2014 14:46:02 +0100 Subject: QNX: Fix touch position Change-Id: I8e4f83f58fbb31f7cffdf74b0ce431a6fd46f13b Reviewed-by: Bernd Weimer Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index 178ea121e6..5724fbd92a 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -457,7 +457,7 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0] - (touchArea[0]>>1), w->geometry().top() + windowPos[1] - (touchArea[1]>>1), - 0.0, 0.0); + (touchArea[0]>>1), (touchArea[1]>>1)); QWindow *parent = w->parent(); while (parent) { m_touchPoints[touchId].area.translate(parent->geometry().topLeft()); -- cgit v1.2.3 From d5dcd6d16647e4ecac239fa26ade5963f0e3f933 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Thu, 13 Mar 2014 19:49:33 +0400 Subject: Add AArch64 support to qfilesystemwatcher_inotify.cpp Based on a patch by Marcin Juszkiewicz , licensed under CC0 (aka Public Domain) or BSD license. Change-Id: I60815d6893c7a9d2873864ff626b865881ec5ee9 Reviewed-by: Lars Knoll --- src/corelib/io/qfilesystemwatcher_inotify.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 5fd20c6d74..3031c7a27e 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -138,6 +138,11 @@ # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 # define __NR_inotify_init1 328 +#elif defined (__aarch64__) +# define __NR_inotify_init1 26 +# define __NR_inotify_add_watch 27 +# define __NR_inotify_rm_watch 28 +// no inotify_init for aarch64 #else # error "This architecture is not supported. Please see http://www.qt-project.org/" #endif @@ -155,7 +160,11 @@ static inline int syscall(...) { return -1; } static inline int inotify_init() { +#ifdef __NR_inotify_init return syscall(__NR_inotify_init); +#else + return syscall(__NR_inotify_init1, 0); +#endif } static inline int inotify_add_watch(int fd, const char *name, __u32 mask) -- cgit v1.2.3 From d7eb0a632a791d528a819666582a29f4bfed12e4 Mon Sep 17 00:00:00 2001 From: Alejandro Exojo Date: Mon, 10 Mar 2014 10:59:36 +0100 Subject: Fix one bogus print to stderr: use toLocal8Bit() Change-Id: I86341ccbd0251a9c858a5e1a9b7ea291d73cda01 Reviewed-by: Robin Burchell Reviewed-by: Kai Koehne --- src/corelib/global/qlogging.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index d8ef8a57a8..f67b87e2bc 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1225,7 +1225,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con logMessage.chop(1); systemd_default_message_handler(type, context, logMessage); } else { - fprintf(stderr, "%s", logMessage.toUtf8().constData()); + fprintf(stderr, "%s", logMessage.toLocal8Bit().constData()); fflush(stderr); } #elif defined(Q_OS_ANDROID) -- cgit v1.2.3 From f1f603bd0be50d65cc17c37e42b3bc291a7e748a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 13 Mar 2014 11:57:49 +0100 Subject: Fix dynamic opengl build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some ifdefs were slightly incorrect. Change-Id: I5ffb162becb040c91ed56f36c6126c59f67c367a Reviewed-by: Friedemann Kleint Reviewed-by: Jørgen Lind --- src/gui/opengl/qopenglfunctions.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 84c70606b1..fe6eb4c098 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -3155,8 +3155,7 @@ static void QOPENGLF_APIENTRY qopenglfResolveGetBufferSubData(GLenum target, qop (target, offset, size, data); } -#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_DYNAMIC) - +#ifndef QT_OPENGL_ES_2 // Desktop only static void QOPENGLF_APIENTRY qopenglfResolveGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) @@ -3164,6 +3163,7 @@ static void QOPENGLF_APIENTRY qopenglfResolveGetTexLevelParameteriv(GLenum targe RESOLVE_FUNC_VOID(0, GetTexLevelParameteriv)(target, level, pname, params); } +#ifndef QT_OPENGL_DYNAMIC // Special translation functions for ES-specific calls on desktop GL static void QOPENGLF_APIENTRY qopenglfTranslateClearDepthf(GLclampf depth) @@ -3176,7 +3176,9 @@ static void QOPENGLF_APIENTRY qopenglfTranslateDepthRangef(GLclampf zNear, GLcla ::glDepthRange(zNear, zFar); } -#endif // !ES2 && !DYNAMIC +#endif // QT_OPENGL_DYNAMIC + +#endif // QT_OPENGL_ES2 QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) { -- cgit v1.2.3 From 6b56b2ddb2c3b744047cd35cc88a16531a2d3048 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 13 Mar 2014 13:31:49 +0100 Subject: Disable QtOpenGL in dynamicgl builds Migrating this is out of scope for the time being. Change-Id: Iac4a98d8db8e132a6ffa28075548fe2af76637fc Reviewed-by: Friedemann Kleint --- src/src.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/src.pro b/src/src.pro index 687f2502ab..0d854a85c1 100644 --- a/src/src.pro +++ b/src/src.pro @@ -148,7 +148,7 @@ contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent SUBDIRS += src_tools_uic src_widgets TOOLS += src_tools_uic src_plugins.depends += src_widgets - contains(QT_CONFIG, opengl(es1|es2)?) { + contains(QT_CONFIG, opengl(es1|es2)?):!contains(QT_CONFIG, dynamicgl) { SUBDIRS += src_opengl src_plugins.depends += src_opengl } -- cgit v1.2.3 From bcfc68f9cd00982decd7ceb312966caf6b1ca05e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 29 Jan 2014 08:38:40 +0100 Subject: Use Uniform Type Identifiers to detect OS X bundles Following Apple's documentation, the first step to identify a bundle is to check if it has a known extension. Currently, it's done using string comparisons ored in an if statement. The list is not complete and new types, whether provided by a system update or other means, can't be detected. The new approach is to use Uniform Type Identifier which queries the OS directly to check whether the extension conforms to kUTTypeBundle. That includes e.g. applications, frameworks etc. Task-number: QTBUG-31884 Change-Id: Ief73a83904adf27ccb71b0070e67cba081d1fd4a Reviewed-by: Jake Petroules Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_unix.cpp | 48 ++++++++++++------------------- 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index ea3a3ca13d..6c0f31fb55 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2013 Samuel Gaist > ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Samuel Gaist ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -89,35 +89,23 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e QFileInfo info(entry.filePath()); QString suffix = info.suffix(); - // First step: is the extenstion known ? - if (suffix == QLatin1String("app") - || suffix == QLatin1String("debug") - || suffix == QLatin1String("profile") - || suffix == QLatin1String("bundle") - || suffix == QLatin1String("pkg")) { - return true; - } - - // Second step: check if an application knows the package type - const QByteArray &native = entry.nativeFilePath(); - const char *nativeFilePath = native.constData(); - int nativeFilePathLength = native.size(); - - QCFType path = CFStringCreateWithBytes(0, - reinterpret_cast(nativeFilePath), - nativeFilePathLength, - kCFStringEncodingUTF8, - false); - - QCFType url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true); - - UInt32 type, creator; - // Well created packages have the PkgInfo file - if (CFBundleGetPackageInfoInDirectory(url, &type, &creator)) - return true; - - // Find if an application other than Finder claims to know how to handle the package if (suffix.length() > 0) { + // First step: is the extension known ? + CFStringRef extensionRef = QCFString::toCFStringRef(suffix); + CFStringRef uniformTypeIdentifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extensionRef, NULL); + if (UTTypeConformsTo(uniformTypeIdentifier, kUTTypeBundle)) + return true; + + // Second step: check if an application knows the package type + CFStringRef path = QCFString::toCFStringRef(entry.filePath()); + QCFType url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true); + + UInt32 type, creator; + // Well created packages have the PkgInfo file + if (CFBundleGetPackageInfoInDirectory(url, &type, &creator)) + return true; + + // Find if an application other than Finder claims to know how to handle the package QCFType application; LSGetApplicationForURL(url, kLSRolesEditor|kLSRolesViewer|kLSRolesViewer, @@ -134,7 +122,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e // Third step: check if the directory has the package bit set FSRef packageRef; - FSPathMakeRef((UInt8 *)nativeFilePath, &packageRef, NULL); + FSPathMakeRef((UInt8 *)entry.nativeFilePath().constData(), &packageRef, NULL); FSCatalogInfo catalogInfo; FSGetCatalogInfo(&packageRef, -- cgit v1.2.3 From 42afaa992a24d8f423f24f279b5514cf914a3da0 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 13 Mar 2014 18:58:12 +0200 Subject: d3dcompiler_qt: Remove control file semantics This simplifies the compiler control semantics by always using the packaged compiler if it is available. With no packaged compiler, the service is assumed to be running if the directory structure is present. Use of a packaged library can be overridden by setting the environment variable QT_D3DCOMPILER_DISABLE_DLL to 1. When the runtime compiler is used, the source will no longer be logged, and the compilation output will no longer be cached. Change-Id: Ib07f517e7043d7785bdfa9da55abd34df518eeed Reviewed-by: Oliver Wolff --- src/angle/src/d3dcompiler/main.cpp | 48 ++++++++++++++------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/angle/src/d3dcompiler/main.cpp b/src/angle/src/d3dcompiler/main.cpp index d2bb43ea9f..7742596226 100644 --- a/src/angle/src/d3dcompiler/main.cpp +++ b/src/angle/src/d3dcompiler/main.cpp @@ -180,22 +180,32 @@ HRESULT WINAPI D3DCompile( const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **errorMsgs) { + // Shortcut to compile using the runtime compiler if it is available + static bool compilerAvailable = + !qgetenv("QT_D3DCOMPILER_DISABLE_DLL").toInt() && D3DCompiler::loadCompiler(); + if (compilerAvailable) { + HRESULT hr = D3DCompiler::compile(data, data_size, filename, defines, include, entrypoint, + target, sflags, eflags, shader, errorMsgs); + return hr; + } + static bool initialized = false; - static bool serviceAvailable = false; static QString binaryPath; static QString sourcePath; if (!initialized) { QString base; - if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR")) { + if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR")) base = QString::fromLocal8Bit(qgetenv("QT_D3DCOMPILER_DIR")); - } else { + + if (base.isEmpty()) { const QString location = QStandardPaths::writableLocation(QStandardPaths::DataLocation); if (!location.isEmpty()) base = location + QStringLiteral("/d3dcompiler"); } + // Unless the service has run, this directory won't exist. QDir baseDir(base); - if (!base.isEmpty() && baseDir.exists()) { + if (baseDir.exists()) { // Check if we have can read/write blobs if (baseDir.exists(QStringLiteral("binary"))) { binaryPath = baseDir.absoluteFilePath(QStringLiteral("binary/")); @@ -211,14 +221,10 @@ HRESULT WINAPI D3DCompile( qCWarning(QT_D3DCOMPILER) << "D3D compiler base directory exists, but the source directory does not.\n" "Check the compiler service."; } - - // Look for a file, "control", and check if it has been touched in the last 60 seconds - QFileInfo control(baseDir.absoluteFilePath(QStringLiteral("control"))); - serviceAvailable = control.exists() && control.lastModified().secsTo(QDateTime::currentDateTime()) < 60; } else { qCWarning(QT_D3DCOMPILER) << "D3D compiler base directory does not exist:" << QDir::toNativeSeparators(base) - << "\nThe compiler service won't be used."; + << "\nCheck that the compiler service is running."; } initialized = true; @@ -259,8 +265,8 @@ HRESULT WINAPI D3DCompile( } } - // Shader blob is not available, compile with compilation service if possible - if (!sourcePath.isEmpty() && serviceAvailable) { + // Shader blob is not available; write out shader source + if (!sourcePath.isEmpty()) { // Dump source to source path; wait for blob to appear QFile source(sourcePath + fileName); if (!source.open(QFile::WriteOnly)) { @@ -292,24 +298,6 @@ HRESULT WINAPI D3DCompile( return E_ABORT; } - // Fall back to compiler DLL - if (D3DCompiler::loadCompiler()) { - HRESULT hr = D3DCompiler::compile(data, data_size, filename, defines, include, entrypoint, - target, sflags, eflags, shader, errorMsgs); - // Cache shader - if (SUCCEEDED(hr) && !binaryPath.isEmpty()) { - const QByteArray blobContents = QByteArray::fromRawData( - reinterpret_cast((*shader)->GetBufferPointer()), (*shader)->GetBufferSize()); - - QFile blob(binaryPath + fileName); - if (blob.open(QFile::WriteOnly) && blob.write(blobContents)) - qCDebug(QT_D3DCOMPILER) << "Cached shader blob at" << blob.fileName(); - else - qCDebug(QT_D3DCOMPILER) << "Unable to write shader blob at" << blob.fileName(); - } - return hr; - } - - *errorMsgs = new D3DCompiler::Blob("Unable to load D3D compiler DLL."); + *errorMsgs = new D3DCompiler::Blob("No shader compiler or service could be found."); return E_FAIL; } -- cgit v1.2.3 From 60f0a97eddfad0cfe2c00dd7a6fb15b94a2260c9 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 13 Mar 2014 13:10:47 +0100 Subject: iOS: fix build failure __IPHONE_NA not defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __IPHONE_NA was previously defined to 9999, but with iPhoneOS7.1.sdk it is now undefined. From Availability.h: "__IPHONE_NA is not defined to a value but is uses as a token by macros to indicate that the API is unavailable" This causes Qt to evaluate QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE to true when given __IPHONE_NA as argument. And then the build will fail. Change-Id: I11f1d0285329d90c633c00c0c4d446ef5cd8089b Reviewed-by: Tor Arne Vestbø --- src/corelib/global/qglobal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index b2f9e29b44..0e5c4965f9 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -534,8 +534,8 @@ Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max #ifdef Q_OS_DARWIN # define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) \ - ((defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= osx) || \ - (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= ios)) + ((defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && osx != __MAC_NA && __MAC_OS_X_VERSION_MAX_ALLOWED >= osx) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MAX_ALLOWED >= ios)) # define QT_MAC_DEPLOYMENT_TARGET_BELOW(osx, ios) \ ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && osx != __MAC_NA && __MAC_OS_X_VERSION_MIN_REQUIRED < osx) || \ -- cgit v1.2.3 From 9ceeaaac7984523fdc08c2040fcadf5698254c2d Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 14 Mar 2014 09:00:26 +0200 Subject: WinRT: Add debug message handler for winrtrunner By placing debug messages in shared memory, the application can share debug messages with winrtrunner (or any utility which passes -qdevel to the app and opens the corresponding shared memory area). Task-number: QTBUG-37308 Change-Id: Id0e04cfd5f0f701d552a448f780788c7cbf9b438 Reviewed-by: Oliver Wolff --- src/winmain/qtmain_winrt.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src') diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index 151294d2c4..22d3f5bd91 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -81,6 +81,27 @@ typedef ITypedEventHandler(data) + 1, 4096 - sizeof(quint32), + message.data(), (message.length() + 1) * sizeof(wchar_t)); + UnmapViewOfFile(data); + SetEvent(event); +#endif // !Q_OS_WINPHONE + defaultMessageHandler(type, context, message); +} + class AppContainer : public Microsoft::WRL::RuntimeClass { public: @@ -127,6 +148,10 @@ public: // (Unused) handle will automatically be closed when the app exits CreateFile2(reinterpret_cast(pidFileName.utf16()), 0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, ¶ms); + // Install the develMode message handler +#ifndef Q_OS_WINPHONE + defaultMessageHandler = qInstallMessageHandler(devMessageHandler); +#endif } // Wait for debugger before continuing if (debugWait) { -- cgit v1.2.3 From 176342e70a1ba7864a5b5dac14d12d4091ef5bd9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 13 Mar 2014 14:10:09 +0100 Subject: QWindowsXP/VistaStyle: Fix detection of item view delegate line edits. The old code tried to check the 2nd parent for inheritance from QAbstractItemView. This also triggers for line edits on a QDialog parented on the item view. Introduce convenience function that checks for top levels in the chain. Task-number: QTBUG-37504 Change-Id: I932f8efdb4764e9b1eea84c802bf7e8718338e1d Reviewed-by: J-P Nurmi Reviewed-by: Jens Bache-Wiig --- src/widgets/styles/qwindowsvistastyle.cpp | 9 +-------- src/widgets/styles/qwindowsxpstyle.cpp | 21 ++++++++++++++------- src/widgets/styles/qwindowsxpstyle_p_p.h | 1 + 3 files changed, 16 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 6955ec83e0..9c3e1eac99 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -626,14 +626,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt anim->paint(painter, option); } else { QPainter *p = painter; - QWidget *parentWidget = 0; - if (widget) { - parentWidget = widget->parentWidget(); - if (parentWidget) - parentWidget = parentWidget->parentWidget(); - } - if (widget && widget->inherits("QLineEdit") - && parentWidget && parentWidget->inherits("QAbstractItemView")) { + if (QWindowsXPStylePrivate::isItemViewDelegateLineEdit(widget)) { // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. QPen oldPen = p->pen(); // Inner white border diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 63ed3ef7c8..e694eb4e7e 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -346,6 +346,19 @@ QString QWindowsXPStylePrivate::themeName(int theme) QString(); } +bool QWindowsXPStylePrivate::isItemViewDelegateLineEdit(const QWidget *widget) +{ + if (!widget) + return false; + const QWidget *parent1 = widget->parentWidget(); + // Exlude dialogs or other toplevels parented on item views. + if (!parent1 || parent1->isWindow()) + return false; + const QWidget *parent2 = parent1->parentWidget(); + return parent2 && widget->inherits("QLineEdit") + && parent2->inherits("QAbstractItemView"); +} + /*! \internal This function will always return a valid window handle, and might create a limbo widget to do so. @@ -1548,13 +1561,7 @@ case PE_Frame: } case PE_FrameLineEdit: { // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. - QWidget *parentWidget = 0; - if (widget) - parentWidget = widget->parentWidget(); - if (parentWidget) - parentWidget = parentWidget->parentWidget(); - if (widget && widget->inherits("QLineEdit") - && parentWidget && parentWidget->inherits("QAbstractItemView")) { + if (QWindowsXPStylePrivate::isItemViewDelegateLineEdit(widget)) { QPen oldPen = p->pen(); // Inner white border p->setPen(QPen(option->palette.base().color(), 1)); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 27d9c9acc9..7327fa5581 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -350,6 +350,7 @@ public: static HTHEME createTheme(int theme, HWND hwnd); static QString themeName(int theme); static inline bool hasTheme(int theme) { return theme >= 0 && theme < NThemes && m_themes[theme]; } + static bool isItemViewDelegateLineEdit(const QWidget *widget); QIcon dockFloat, dockClose; -- cgit v1.2.3 From c42ac8173eb50f4d42e5a2f2d94d39195dad1b47 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Fri, 14 Mar 2014 06:56:59 +0000 Subject: Fix a probably copy/paste issue from drawImage in the drawPixmap snippet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia2b34e3ee6954342501a805f9e047cb90078e9d5 Reviewed-by: Martin Smith Reviewed-by: Topi Reiniö --- src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp b/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp index 6a012879d4..144858816b 100644 --- a/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp +++ b/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp @@ -207,7 +207,7 @@ QRectF source(0.0, 0.0, 70.0, 40.0); QPixmap pixmap(":myPixmap.png"); QPainter(this); -painter.drawPixmap(target, image, source); +painter.drawPixmap(target, pixmap, source); //! [16] -- cgit v1.2.3 From 2bbdc6358f73ce167140bace821d606e720c0ded Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Thu, 13 Mar 2014 16:55:28 +0100 Subject: HTTP internals: keep consistent state in channel and protocol handler It could be that the channel has its reply already reset to 0, while the protocol handler thinks the reply is still active, which might lead to weird behavior including hard to reproduce crashes. Task-number: QTBUG-37424 Change-Id: I89b65d34caaa546a343edc2ee205aa76425de88f Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnection.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 87511076d3..32b6d902d0 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -377,6 +377,8 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, // Clean the channel channels[i].close(); channels[i].reply = 0; + if (channels[i].protocolHandler) + channels[i].protocolHandler->setReply(0); channels[i].request = QHttpNetworkRequest(); if (socket) channels[i].requeueCurrentlyPipelinedRequests(); @@ -826,6 +828,8 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) // is the reply associated the currently processing of this channel? if (channels[i].reply == reply) { channels[i].reply = 0; + if (channels[i].protocolHandler) + channels[i].protocolHandler->setReply(0); channels[i].request = QHttpNetworkRequest(); channels[i].resendCurrent = false; -- cgit v1.2.3 From 7fba691110f3c85974b18edb760303e0b0993787 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 7 Mar 2014 12:36:23 +0100 Subject: Docs: Clarify QOpenGLFunctions::functions() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ifb6fdc3de7f93a1632b396eaaa14078546cac4dd Reviewed-by: Jørgen Lind Reviewed-by: Sean Harmer --- src/gui/kernel/qopenglcontext.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index fb7d15c160..7ccdd7395b 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -578,6 +578,9 @@ bool QOpenGLContext::isValid() const without having to manage it manually. The context or a sharing context must be current. + + The returned QOpenGLFunctions instance is ready to be used and it + does not need initializeOpenGLFunctions() to be called. */ QOpenGLFunctions *QOpenGLContext::functions() const { -- cgit v1.2.3 From 82fd626ded2282a38930ddeb8dbf26bffdae235e Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 13 Mar 2014 16:24:08 +0100 Subject: Document %{if-category} in default message pattern Commit 15ddb91b introduced %{if-category}, and changed the default message pattern. Adapt the documentation accordingly. Change-Id: I1d500122300c4d62171de3607553b3a5a822d4a7 Reviewed-by: Jerome Pasion --- src/corelib/global/qlogging.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index f67b87e2bc..8c1d8b867d 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1484,12 +1484,15 @@ void qErrnoWarning(int code, const char *msg, ...) \c %{if-warning}, \c %{if-critical} or \c %{if-fatal} followed by an \c %{endif}. What is inside the \c %{if-*} and \c %{endif} will only be printed if the type matches. + Finally, text inside \c %{if-category} ... \c %{endif} is only printed if the category + is not the default one. + Example: \code QT_MESSAGE_PATTERN="[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}" \endcode - The default \a pattern is "%{message}". + The default \a pattern is "%{if-category}%{category}: %{endif}%{message}". The \a pattern can also be changed at runtime by setting the QT_MESSAGE_PATTERN environment variable; if both qSetMessagePattern() is called and QT_MESSAGE_PATTERN is -- cgit v1.2.3 From 4b0ad2fcc8689a780b3337c1f122d413eba713f8 Mon Sep 17 00:00:00 2001 From: Lorenz Haas Date: Thu, 13 Mar 2014 17:06:04 +0100 Subject: Doc: Fix syntax/compiler error in QThread snippet Change-Id: If64e01099b50f15b5cf7cdb0890dfa4f7625126d Reviewed-by: Olivier Goffart --- src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp index 54c8f801cd..5c6055defe 100644 --- a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp @@ -47,7 +47,7 @@ class WorkerThread : public QThread Q_OBJECT void run() Q_DECL_OVERRIDE { QString result; - /* expensive or blocking operation */ + /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } signals: @@ -71,7 +71,8 @@ class Worker : public QObject public slots: void doWork(const QString ¶meter) { - // ... + QString result; + /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } -- cgit v1.2.3 From 51e5378113ac185ce9b3f64417416243050f6335 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 11 Mar 2014 09:35:35 +0100 Subject: Use QCommandLineParser in example dnslookup. Show how use QCommandLineParser with additional parameter checking for custom options and positional arguments. Also explain how to display help in GUI applications. Change-Id: I03513e09b7dd5b150259593da0af2ef2a281cab2 Reviewed-by: David Faure --- src/corelib/doc/qtcore.qdocconf | 3 +- src/corelib/tools/qcommandlineparser.cpp | 72 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index 18fdfb18f3..2ad24d33b1 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -37,7 +37,8 @@ exampledirs += \ snippets \ ../../../examples/threads/ \ ../../../examples/tools/ \ - ../../../examples/json/ + ../../../examples/json/ \ + ../../../examples/network/dnslookup imagedirs += images diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index c860b4d155..505ab5f46d 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -187,6 +187,78 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const QCoreApplication::arguments() before QCommandLineParser defines the \c{profile} option and parses the command line. + \section2 How to Use QCommandLineParser in Complex Applications + + In practice, additional error checking needs to be performed on the positional + arguments and option values. For example, ranges of numbers should be checked. + + It is then advisable to introduce a function to do the command line parsing + which takes a struct or class receiving the option values returning an + enumeration representing the result. The dnslookup example of the QtNetwork + module illustrates this: + + \snippet dnslookup.h 0 + + \snippet dnslookup.cpp 0 + + In the main function, help should be printed to the standard output if the help option + was passed and the application should return the exit code 0. + + If an error was detected, the error message should be printed to the standard + error output and the application should return an exit code other than 0. + + \snippet dnslookup.cpp 1 + + A special case to consider here are GUI applications on Windows and mobile + platforms. These applications may not use the standard output or error channels + since the output is either discarded or not accessible. + + For such GUI applications, it is recommended to display help texts and error messages + using a QMessageBox. To preserve the formatting of the help text, rich text + with \c
 elements should be used:
+
+    \code
+
+    switch (parseCommandLine(parser, &query, &errorMessage)) {
+    case CommandLineOk:
+        break;
+    case CommandLineError:
+#ifdef Q_OS_WIN
+        QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
+                             "

" + errorMessage + "

"
+                             + parser.helpText() + "
"); +#else + fputs(qPrintable(errorMessage), stderr); + fputs("\n\n", stderr); + fputs(qPrintable(parser.helpText()), stderr); +#endif + return 1; + case CommandLineVersionRequested: +#ifdef Q_OS_WIN + QMessageBox::information(0, QGuiApplication::applicationDisplayName(), + QGuiApplication::applicationDisplayName() + ' ' + + QCoreApplication::applicationVersion()); +#else + printf("%s %s\n", QGuiApplication::applicationDisplayName(), + qPrintable(QCoreApplication::applicationVersion())); +#endif + return 0; + case CommandLineHelpRequested: +#ifdef Q_OS_WIN + QMessageBox::warning(0, QGuiApplication::applicationDisplayName(), + "
"
+                             + parser.helpText() + "
"); + return 0; +#else + parser.showHelp(); + Q_UNREACHABLE(); +#endif + } + \endcode + + However, this does not apply to the dnslookup example, because it is a + console application. + \sa QCommandLineOption, QCoreApplication */ -- cgit v1.2.3 From 49b14f7a8b8e88833a5357215bc0311907f794fd Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 10 Mar 2014 10:16:21 +0100 Subject: Remove the _qt_filedialog_xxx hooks These internal and obsolete hooks are no longer used. The correct way to provide platform dialogs in Qt 5.x is to implement a platform theme plugin, as was done for GTK+ 2.x. Change-Id: I3f1474fbf760130106b3c47173eaedd2f1a919bf Reviewed-by: Shawn Rutledge Reviewed-by: David Faure --- src/widgets/dialogs/qfiledialog.cpp | 49 +++---------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index bea92e9f84..bb73ef5cda 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -79,35 +79,6 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QString, lastVisitedDir) -/* - \internal - - Exported hooks that can be used to customize the static functions. - */ -typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); -Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook = 0; - -typedef QUrl (*_qt_filedialog_existing_directory_url_hook)(QWidget *parent, const QString &caption, const QUrl &dir, QFileDialog::Options options, const QStringList &supportedSchemes); -Q_WIDGETS_EXPORT _qt_filedialog_existing_directory_url_hook qt_filedialog_existing_directory_url_hook = 0; - -typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); -Q_WIDGETS_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook = 0; - -typedef QUrl (*_qt_filedialog_open_file_url_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes); -Q_WIDGETS_EXPORT _qt_filedialog_open_file_url_hook qt_filedialog_open_file_url_hook = 0; - -typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); -Q_WIDGETS_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook = 0; - -typedef QList (*_qt_filedialog_open_file_urls_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes); -Q_WIDGETS_EXPORT _qt_filedialog_open_file_urls_hook qt_filedialog_open_file_urls_hook = 0; - -typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); -Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook = 0; - -typedef QUrl (*_qt_filedialog_save_file_url_hook)(QWidget * parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes); -Q_WIDGETS_EXPORT _qt_filedialog_save_file_url_hook qt_filedialog_save_file_url_hook = 0; - /*! \class QFileDialog \brief The QFileDialog class provides a dialog that allow users to select files or directories. @@ -2099,8 +2070,6 @@ QString QFileDialog::getOpenFileName(QWidget *parent, QString *selectedFilter, Options options) { - if (qt_filedialog_open_filename_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_open_filename_hook(parent, caption, dir, filter, selectedFilter, options); QFileDialogArgs args; args.parent = parent; args.caption = caption; @@ -2162,8 +2131,7 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent, Options options, const QStringList &supportedSchemes) { - if (qt_filedialog_open_file_url_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_open_file_url_hook(parent, caption, dir, filter, selectedFilter, options, supportedSchemes); + Q_UNUSED(supportedSchemes); // Falls back to local file return QUrl::fromLocalFile(getOpenFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options)); @@ -2225,8 +2193,6 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent, QString *selectedFilter, Options options) { - if (qt_filedialog_open_filenames_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_open_filenames_hook(parent, caption, dir, filter, selectedFilter, options); QFileDialogArgs args; args.parent = parent; args.caption = caption; @@ -2290,8 +2256,7 @@ QList QFileDialog::getOpenFileUrls(QWidget *parent, Options options, const QStringList &supportedSchemes) { - if (qt_filedialog_open_file_urls_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_open_file_urls_hook(parent, caption, dir, filter, selectedFilter, options, supportedSchemes); + Q_UNUSED(supportedSchemes); // Falls back to local files QList urls; @@ -2360,8 +2325,6 @@ QString QFileDialog::getSaveFileName(QWidget *parent, QString *selectedFilter, Options options) { - if (qt_filedialog_save_filename_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_save_filename_hook(parent, caption, dir, filter, selectedFilter, options); QFileDialogArgs args; args.parent = parent; args.caption = caption; @@ -2426,8 +2389,7 @@ QUrl QFileDialog::getSaveFileUrl(QWidget *parent, Options options, const QStringList &supportedSchemes) { - if (qt_filedialog_save_file_url_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_save_file_url_hook(parent, caption, dir, filter, selectedFilter, options, supportedSchemes); + Q_UNUSED(supportedSchemes); // Falls back to local file return QUrl::fromLocalFile(getSaveFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options)); @@ -2477,8 +2439,6 @@ QString QFileDialog::getExistingDirectory(QWidget *parent, const QString &dir, Options options) { - if (qt_filedialog_existing_directory_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_existing_directory_hook(parent, caption, dir, options); QFileDialogArgs args; args.parent = parent; args.caption = caption; @@ -2537,8 +2497,7 @@ QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent, Options options, const QStringList &supportedSchemes) { - if (qt_filedialog_existing_directory_url_hook && !(options & DontUseNativeDialog)) - return qt_filedialog_existing_directory_url_hook(parent, caption, dir, options, supportedSchemes); + Q_UNUSED(supportedSchemes); // Falls back to local file return QUrl::fromLocalFile(getExistingDirectory(parent, caption, dir.toLocalFile(), options)); -- cgit v1.2.3 From 4b0016f045a4f78b8cc9bb6e8ded40db0f8a30ec Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 11 Mar 2014 20:55:48 +0100 Subject: Cocoa: Get rid of the forward window pointer asap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As soon as we receive an event not related to dragging a QDockWidget out of its area (or a similar use case), we no longer need the forward window. Task-number: QTBUG-37265 Change-Id: I310e9cc2cf099c76e7a88427826d4b97ca0cd9b9 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 90d56bc3f3..872ae5ebbb 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -562,9 +562,11 @@ static QTouchDevice *touchDevice = 0; QPointF qtWindowPoint; QPointF qtScreenPoint; QNSView *targetView = self; - if (m_platformWindow && m_platformWindow->m_forwardWindow - && (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)) { - targetView = m_platformWindow->m_forwardWindow->m_qtView; + if (m_platformWindow && m_platformWindow->m_forwardWindow) { + if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp) + targetView = m_platformWindow->m_forwardWindow->m_qtView; + else + m_platformWindow->m_forwardWindow = 0; } [targetView convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; -- cgit v1.2.3 From 19532eec2ae1a723e981e3f90730905cabedb9c8 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 10 Mar 2014 14:44:22 +0100 Subject: Fix casting and overallocation in qregion.cpp The POINTBLOCK struct in qregion.cpp is badly defined. By using ints as the base storage of the internal array it forces not only bad casting from int to QPoint, but also allocates an array four times too big. This patch changes to char, since a char pointer may alias anything and this gives the right size of the array. Change-Id: I608eaf39ac7306c71314a139bed6e2352249c0ab Reviewed-by: Gunnar Sletta --- src/gui/painting/qregion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index beeac6bd43..20c62fdd9d 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -1713,7 +1713,7 @@ QT_END_INCLUDE_NAMESPACE * the buffers together */ typedef struct _POINTBLOCK { - int data[NUMPTSTOBUFFER * sizeof(QPoint)]; + char data[NUMPTSTOBUFFER * sizeof(QPoint)]; QPoint *pts; struct _POINTBLOCK *next; } POINTBLOCK; -- cgit v1.2.3 From 77bf302ce2d69fb01e41b02329fdb8419b6e9e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 12 Mar 2014 12:34:42 +0100 Subject: Prevent DrawTextItemDevice::metric warning on Mac Implement PdmDevicePixelRatio. Task-number: QTBUG-36419 Change-Id: I4d2822d01e08c80e9b829d5f524e8e761e694fba Reviewed-by: Gabriel de Dietrich --- src/gui/text/qstatictext.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index b153219136..0afc6f9259 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -573,6 +573,9 @@ namespace { case PdmDepth: val = 24; break; + case PdmDevicePixelRatio: + val = 1; + break; default: val = 0; qWarning("DrawTextItemDevice::metric: Invalid metric command"); -- cgit v1.2.3 From 3d2160056e409ad2508a8bff4288944d37e32f85 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 12 Mar 2014 13:38:24 +0100 Subject: Resurrect QGLWidget::renderText() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variant taking x, y, z has been broken in all Qt 5.x releases. This is now corrected by making the GL2 paint engine capable of applying a Z translation. Task-number: QTBUG-31156 Change-Id: I119566e9e9577f6cdf7e8bae56cac1e34995e622 Reviewed-by: Jørgen Lind --- .../gl2paintengineex/qglengineshadermanager.cpp | 3 ++- .../gl2paintengineex/qglengineshadermanager_p.h | 1 + .../gl2paintengineex/qglengineshadersource_p.h | 5 ++++- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 17 +++++++++++++++++ .../gl2paintengineex/qpaintengineex_opengl2_p.h | 9 ++++++++- src/opengl/qgl.cpp | 20 ++++++++------------ 6 files changed, 40 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 56f3f5ad0a..f266318ba6 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -534,7 +534,8 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id) "invertedTextureSize", "brushTransform", "brushTexture", - "matrix" + "matrix", + "translateZ" }; if (uniformLocations.at(id) == GLuint(-1)) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index bbd9d86773..166d9a0593 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -444,6 +444,7 @@ public: BrushTransform, BrushTexture, Matrix, + TranslateZ, NumUniforms }; diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 90bd7edf54..aad2c1f7db 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -106,10 +106,13 @@ static const char* const qglslPositionOnlyVertexShader = "\n\ static const char* const qglslComplexGeometryPositionOnlyVertexShader = "\n\ uniform highp mat3 matrix; \n\ + uniform highp float translateZ; \n\ attribute highp vec2 vertexCoordsArray; \n\ void setPosition(void) \n\ { \n\ - gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\ + vec3 v = matrix * vec3(vertexCoordsArray, 1.0); \n\ + vec4 vz = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, translateZ, 1) * vec4(v, 1.0); \n\ + gl_Position = vec4(vz.xyz, 1.0);\n\ } \n"; static const char* const qglslUntransformedPositionVertexShader = "\n\ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index fd64a4a71f..2b49e4d2d1 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1158,6 +1158,7 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) brushUniformsDirty = true; opacityUniformDirty = true; matrixUniformDirty = true; + translateZUniformDirty = true; } if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode) @@ -1174,6 +1175,12 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) matrixUniformDirty = false; } + if (translateZUniformDirty && shaderManager->hasComplexGeometry()) { + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::TranslateZ), + translateZ); + translateZUniformDirty = false; + } + return changed; } @@ -2011,6 +2018,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->matrixDirty = true; d->compositionModeDirty = true; d->opacityUniformDirty = true; + d->translateZUniformDirty = true; d->needsSync = true; d->useSystemClip = !systemClip().isEmpty(); d->currentBrush = QBrush(); @@ -2375,6 +2383,15 @@ void QGL2PaintEngineExPrivate::systemStateChanged() } } +void QGL2PaintEngineEx::setTranslateZ(GLfloat z) +{ + Q_D(QGL2PaintEngineEx); + if (d->translateZ != z) { + d->translateZ = z; + d->translateZUniformDirty = true; + } +} + void QGL2PaintEngineEx::setState(QPainterState *new_state) { // qDebug("QGL2PaintEngineEx::setState()"); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 33a8869ecf..15ed5bc57d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -158,6 +158,9 @@ public: bool isNativePaintingActive() const; bool requiresPretransformedGlyphPositions(QFontEngine *, const QTransform &) const { return false; } bool shouldDrawCachedGlyphs(QFontEngine *, const QTransform &) const; + + void setTranslateZ(GLfloat z); + private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; @@ -183,7 +186,8 @@ public: snapToPixelGrid(false), nativePaintingActive(false), inverseScale(1), - lastMaskTextureUsed(0) + lastMaskTextureUsed(0), + translateZ(0) { } ~QGL2PaintEngineExPrivate(); @@ -266,6 +270,7 @@ public: bool brushUniformsDirty; bool opacityUniformDirty; bool matrixUniformDirty; + bool translateZUniformDirty; bool stencilClean; // Has the stencil not been used for clipping so far? bool useSystemClip; @@ -309,6 +314,8 @@ public: QVector unusedIBOSToClean; const GLfloat *vertexAttribPointers[3]; + + GLfloat translateZ; }; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 1fbff0f0fe..d676abee47 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4451,12 +4451,6 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font) glDisable(GL_DEPTH_TEST); glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height, 0, 0, 1); - glMatrixMode(GL_MODELVIEW); - - glLoadIdentity(); } else { setAutoBufferSwap(false); // disable glClear() as a result of QPainter::begin() @@ -4567,19 +4561,21 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con } else if (use_scissor_testing) { glEnable(GL_SCISSOR_TEST); } - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); glViewport(0, 0, width, height); - glOrtho(0, width, height, 0, 0, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); glAlphaFunc(GL_GREATER, 0.0); glEnable(GL_ALPHA_TEST); if (use_depth_testing) glEnable(GL_DEPTH_TEST); - glTranslated(0, 0, -win_z); + + // The only option in Qt 5 is the shader-based OpenGL 2 paint engine. + // Setting fixed pipeline transformations is futile. Instead, pass the + // extra values directly and let the engine figure the matrices out. + static_cast(p->paintEngine())->setTranslateZ(-win_z); + qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font); + static_cast(p->paintEngine())->setTranslateZ(0); + if (!reuse_painter) { p->end(); delete p; -- cgit v1.2.3 From 7b8d4cdb1098547ab2d2cc5337cae0496bb4ef61 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 11 Mar 2014 15:09:41 +0100 Subject: Windows native file dialog: Allow for omitting name filter description. Task-number: QTBUG-37329 Change-Id: I644595a292e5b1890b2088b68be595bfcdba9d4d Reviewed-by: Shawn Rutledge Reviewed-by: Oliver Wolff Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 0951009cf0..f70b5b4e2b 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1195,7 +1195,7 @@ static QList filterSpecs(const QStringList &filters, const QRegExp filterSeparatorRE(QStringLiteral("[;\\s]+")); const QString separator = QStringLiteral(";"); Q_ASSERT(filterSeparatorRE.isValid()); - // Split filter specification as 'Texts (*.txt[;] *.doc)' + // Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc' // into description and filters specification as '*.txt;*.doc' foreach (const QString &filterString, filters) { const int openingParenPos = filterString.lastIndexOf(QLatin1Char('(')); @@ -1203,8 +1203,10 @@ static QList filterSpecs(const QStringList &filters, filterString.indexOf(QLatin1Char(')'), openingParenPos + 1) : -1; FilterSpec filterSpec; filterSpec.filter = closingParenPos == -1 ? - QString(QLatin1Char('*')) : + filterString : filterString.mid(openingParenPos + 1, closingParenPos - openingParenPos - 1).trimmed(); + if (filterSpec.filter.isEmpty()) + filterSpec.filter += QLatin1Char('*'); filterSpec.filter.replace(filterSeparatorRE, separator); filterSpec.description = filterString; if (hideFilterDetails && openingParenPos != -1) { // Do not show pattern in description -- cgit v1.2.3 From de5185472651a6051a3c7b6e2519cc5f2b951a62 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 25 Feb 2014 15:27:09 +0100 Subject: iOS: update keyboard rectangle when scrolling the screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we scroll, the keyboard will change position relative to QScreen, even if it appears to stay put. For that reason we also need to update the keyboard rect after doing a scroll. Change-Id: I9bda2ab5b5e4970f488d3e69e44cf58e273f8fcd Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosinputcontext.mm | 32 ++++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 4fe2cae15e..fff7de8170 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -131,16 +131,11 @@ - (void) keyboardDidChangeFrame:(NSNotification *)notification { + Q_UNUSED(notification); if (m_ignoreKeyboardChanges) return; - m_keyboardRect = [self getKeyboardRect:notification]; - m_context->emitKeyboardRectChanged(); - BOOL visible = m_keyboardRect.intersects(fromCGRect([UIScreen mainScreen].bounds)); - if (m_keyboardVisible != visible) { - m_keyboardVisible = visible; - m_context->emitInputPanelVisibleChanged(); - } + [self handleKeyboardRectChanged]; // If the keyboard was visible and docked from before, this is just a geometry // change (normally caused by an orientation change). In that case, update scroll: @@ -172,6 +167,22 @@ m_context->scroll(0); } +- (void) handleKeyboardRectChanged +{ + QRectF rect = m_keyboardEndRect; + rect.moveTop(rect.y() + m_viewController.view.bounds.origin.y); + if (m_keyboardRect != rect) { + m_keyboardRect = rect; + m_context->emitKeyboardRectChanged(); + } + + BOOL visible = m_keyboardEndRect.intersects(fromCGRect([UIScreen mainScreen].bounds)); + if (m_keyboardVisible != visible) { + m_keyboardVisible = visible; + m_context->emitInputPanelVisibleChanged(); + } +} + @end QIOSInputContext::QIOSInputContext() @@ -295,10 +306,15 @@ void QIOSInputContext::scroll(int y) CGRect newBounds = view.bounds; newBounds.origin.y = y; + QPointer self = this; [UIView animateWithDuration:m_keyboardListener->m_duration delay:0 options:m_keyboardListener->m_curve animations:^{ view.bounds = newBounds; } - completion:0]; + completion:^(BOOL){ + if (self) + [m_keyboardListener handleKeyboardRectChanged]; + } + ]; } void QIOSInputContext::update(Qt::InputMethodQueries query) -- cgit v1.2.3 From 287fa94fe2f93e2857a4c15f69435c4ea14de82e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 12 Mar 2014 12:48:19 +0100 Subject: Android: Fix another "QApplication not on main() thread" crash The assets file engine is created before main() is called, thus prepopulate was called before main(). In this function, we created a QDataStream which internally created a QBuffer which inherits from QObject. This caused the main thread pointer to be initialized early, and the old "QApplication is not on the main() thread" warning and crash returned. The fix is to prepopulate the first time the file engine is used instead. Task-number: QTBUG-37444 Change-Id: I2c6e5f1a8ca88b5dc7d8e145fffeb7587dc0e623 Reviewed-by: Paul Olav Tvete --- .../platforms/android/qandroidassetsfileenginehandler.cpp | 11 +++++++++-- .../platforms/android/qandroidassetsfileenginehandler.h | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index b112e265a5..4968b8f188 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -262,17 +262,20 @@ private: AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler() : m_assetsCache(std::max(5, qgetenv("QT_ANDROID_MAX_ASSETS_CACHE_SIZE").toInt())) , m_hasPrepopulatedCache(false) + , m_hasTriedPrepopulatingCache(false) { m_assetManager = QtAndroid::assetManager(); - prepopulateCache(); } AndroidAssetsFileEngineHandler::~AndroidAssetsFileEngineHandler() { } -void AndroidAssetsFileEngineHandler::prepopulateCache() +void AndroidAssetsFileEngineHandler::prepopulateCache() const { + Q_ASSERT(!m_hasTriedPrepopulatingCache); + m_hasTriedPrepopulatingCache = true; + QMutexLocker locker(&m_assetsCacheMutext); Q_ASSERT(m_assetsCache.isEmpty()); @@ -364,7 +367,11 @@ QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &file if (!path.size()) path = fileName.left(fileName.length() - 1).toUtf8(); + m_assetsCacheMutext.lock(); + if (!m_hasTriedPrepopulatingCache) + prepopulateCache(); + QSharedPointer *aad = m_assetsCache.object(path); m_assetsCacheMutext.unlock(); if (!aad) { diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h index d56367d4d8..ac16ad7b79 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h @@ -58,12 +58,13 @@ public: QAbstractFileEngine *create(const QString &fileName) const; private: - void prepopulateCache(); + void prepopulateCache() const; AAssetManager *m_assetManager; mutable QCache> m_assetsCache; mutable QMutex m_assetsCacheMutext; - bool m_hasPrepopulatedCache; + mutable bool m_hasPrepopulatedCache; + mutable bool m_hasTriedPrepopulatingCache; }; #endif // QANDROIDASSETSFILEENGINEHANDLER_H -- cgit v1.2.3 From f9e1e595a9a83a93dea98d7b34bf545d06d01387 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 13 Mar 2014 11:24:38 +0200 Subject: Android: Delay the set of the BackingStore if window->handle() is null. Task-number: QTBUG-37458 Change-Id: Idddfe1876aff3d14d8c6c060d04236c5dc611bce Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../android/qandroidplatformbackingstore.cpp | 21 +++++++++++++++------ .../android/qandroidplatformbackingstore.h | 3 ++- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp index b85b1157a8..ff49f59076 100644 --- a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp +++ b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp @@ -50,11 +50,8 @@ QT_BEGIN_NAMESPACE QAndroidPlatformBackingStore::QAndroidPlatformBackingStore(QWindow *window) : QPlatformBackingStore(window) { - Q_ASSERT(window->handle()); - if (window->surfaceType() == QSurface::RasterSurface) - (static_cast(window->handle()))->setBackingStore(this); - else - qWarning("QAndroidPlatformBackingStore does not support GL windows."); + if (window->handle()) + setBackingStore(window); } QPaintDevice *QAndroidPlatformBackingStore::paintDevice() @@ -64,9 +61,11 @@ QPaintDevice *QAndroidPlatformBackingStore::paintDevice() void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(window); Q_UNUSED(offset); + if (!m_backingStoreSet) + setBackingStore(window); + (static_cast(window->handle()))->repaint(region); } @@ -78,4 +77,14 @@ void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &stat m_image = QImage(size, window()->screen()->handle()->format()); } +void QAndroidPlatformBackingStore::setBackingStore(QWindow *window) +{ + if (window->surfaceType() == QSurface::RasterSurface) { + (static_cast(window->handle()))->setBackingStore(this); + m_backingStoreSet = true; + } else { + qWarning("QAndroidPlatformBackingStore does not support GL windows."); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.h b/src/plugins/platforms/android/qandroidplatformbackingstore.h index e6ea3dcce0..4c24e129c3 100644 --- a/src/plugins/platforms/android/qandroidplatformbackingstore.h +++ b/src/plugins/platforms/android/qandroidplatformbackingstore.h @@ -56,9 +56,10 @@ public: virtual void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); virtual void resize(const QSize &size, const QRegion &staticContents); const QImage image() { return m_image; } - + void setBackingStore(QWindow *window); protected: QImage m_image; + bool m_backingStoreSet = false; }; QT_END_NAMESPACE -- cgit v1.2.3 From 4d56c86f802a49e0fa5481e13ab1f000ff284637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 13 Mar 2014 12:46:10 +0100 Subject: Cocoa: Disable the zoom button when appropriate Disable the zoom (maximize) button for fixed-size windows and customized windows with the MaximizeButton flag not set. Task-number: QTBUG-37078 Change-Id: I6da88496474713de37b48aa65742203632ba99d6 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.h | 1 + src/plugins/platforms/cocoa/qcocoawindow.mm | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 9128b05746..fe82edd618 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -190,6 +190,7 @@ public: NSInteger windowLevel(Qt::WindowFlags flags); NSUInteger windowStyleMask(Qt::WindowFlags flags); void setWindowShadow(Qt::WindowFlags flags); + void setWindowZoomButton(Qt::WindowFlags flags); void setCurrentContext(QCocoaGLContext *context); QCocoaGLContext *currentContext() const; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index c2a0c81b31..957428d043 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -805,6 +805,18 @@ void QCocoaWindow::setWindowShadow(Qt::WindowFlags flags) [m_nsWindow setHasShadow:(keepShadow ? YES : NO)]; } +void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags) +{ + // Disable the zoom (maximize) button for fixed-sized windows and customized + // no-WindowMaximizeButtonHint windows. From a Qt perspective it migth be expected + // that the button would be removed in the latter case, but disabling it is more + // in line with the platform style guidelines. + bool fixedSizeNoZoom = (window()->minimumSize().isValid() && window()->maximumSize().isValid() + && window()->minimumSize() == window()->maximumSize()); + bool customizeNoZoom = ((flags & Qt::CustomizeWindowHint) && !(flags & Qt::WindowMaximizeButtonHint)); + [[m_nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)]; +} + void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) { if (m_nsWindow && !m_isNSWindowChild) { @@ -830,6 +842,7 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) } } #endif + setWindowZoomButton(flags); } m_windowFlags = flags; @@ -993,6 +1006,9 @@ void QCocoaWindow::propagateSizeHints() const QSize maximumSize = window()->maximumSize(); [m_nsWindow setContentMaxSize : NSMakeSize(maximumSize.width(), maximumSize.height())]; + // The window may end up with a fixed size; in this case the zoom button should be disabled. + setWindowZoomButton(m_windowFlags); + // sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be // resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case. if (!window()->sizeIncrement().isEmpty()) -- cgit v1.2.3 From 5334a2cea76473060b4f20aa8f1d5819bb03e6c4 Mon Sep 17 00:00:00 2001 From: Kari Pihkala Date: Thu, 31 Oct 2013 15:23:21 +0200 Subject: Mac: Add support for high-dpi custom pixmap QCursors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For pixmaps with devicePixelRatio greater than 1, create a native cursor that has a normal and a high-dpi representation. Task-number: QTBUG-34116 Change-Id: I1c014d65749add25f2b828837555a1844ede97c1 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoacursor.mm | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 13f6423701..592bfc8e50 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -308,8 +308,22 @@ NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap *bitmap, const QBit NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoint hotspot) { - NSPoint hotSpot = NSMakePoint(hotspot.x(), hotspot.y()); - NSImage *nsimage = static_cast(qt_mac_create_nsimage(pixmap)); + NSPoint hotSpot = NSMakePoint(hotspot.x() / pixmap.devicePixelRatio(), + hotspot.y() / pixmap.devicePixelRatio()); + NSImage *nsimage; + if (pixmap.devicePixelRatio() > 1.0) { + QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); + QPixmap scaledPixmap = pixmap.scaled(layoutSize); + nsimage = static_cast(qt_mac_create_nsimage(scaledPixmap)); + CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage()); + NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; + [nsimage addRepresentation:imageRep]; + [imageRep release]; + CGImageRelease(cgImage); + } else { + nsimage = static_cast(qt_mac_create_nsimage(pixmap)); + } + NSCursor *nsCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot]; [nsimage release]; return nsCursor; -- cgit v1.2.3 From eadaaf69fbb5bf7ff4b50efd41ba621d24fd4f61 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Thu, 6 Mar 2014 14:42:47 +0100 Subject: Cocoa: added queryKeyboardModifiers() in platform plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-37181 Change-Id: I9256d0c9b83d6e5982864dc747586cbe2322b60c Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.h | 1 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoakeymapper.h | 1 + src/plugins/platforms/cocoa/qcocoakeymapper.mm | 5 +++++ 4 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index b1b73e5f08..24adc7a95b 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -129,6 +129,7 @@ public: QCocoaServices *services() const; QVariant styleHint(StyleHint hint) const; + Qt::KeyboardModifiers queryKeyboardModifiers() const; QList possibleKeys(const QKeyEvent *event) const; void updateScreens(); diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 1892a5b6bf..d612c7ff28 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -464,6 +464,11 @@ QVariant QCocoaIntegration::styleHint(StyleHint hint) const return QPlatformIntegration::styleHint(hint); } +Qt::KeyboardModifiers QCocoaIntegration::queryKeyboardModifiers() const +{ + return QCocoaKeyMapper::queryKeyboardModifiers(); +} + QList QCocoaIntegration::possibleKeys(const QKeyEvent *event) const { return mKeyboardMapper->possibleKeys(event); diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.h b/src/plugins/platforms/cocoa/qcocoakeymapper.h index 0629de9317..4f419b3651 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.h +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.h @@ -83,6 +83,7 @@ class QCocoaKeyMapper public: QCocoaKeyMapper(); ~QCocoaKeyMapper(); + static Qt::KeyboardModifiers queryKeyboardModifiers(); QList possibleKeys(const QKeyEvent *event) const; bool updateKeyboard(); void deleteLayouts(); diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm index 0745cc2254..e46eaff6be 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm @@ -346,6 +346,11 @@ QCocoaKeyMapper::~QCocoaKeyMapper() deleteLayouts(); } +Qt::KeyboardModifiers QCocoaKeyMapper::queryKeyboardModifiers() +{ + return qt_mac_get_modifiers(GetCurrentEventKeyModifiers()); +} + bool QCocoaKeyMapper::updateKeyboard() { const UCKeyboardLayout *uchrData = 0; -- cgit v1.2.3 From 2ae50d912389c5da4057fa6e49c662af469d7214 Mon Sep 17 00:00:00 2001 From: Martin Klapetek Date: Tue, 11 Mar 2014 13:39:53 +0100 Subject: Update QScreen::availableGeometry() on _NET_WORKAREA atom changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the window manager sets new workarea using the _NET_WORKAREA xcb atom, QScreen::availableGeometry() does not react to that and returns an invalid available geometry. This patch reacts to that change and updates the QScreen property properly on xcb platform. Change-Id: I8f0b4a27bab0ce450fb7393f4d9a56f3ce9a4ea1 Reviewed-by: Uli Schlachter Reviewed-by: Shawn Rutledge Reviewed-by: Friedemann Kleint Reviewed-by: Jørgen Lind Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbscreen.cpp | 3 ++- src/plugins/platforms/xcb/qxcbwindow.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index b1ef3182ba..9f19841437 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -371,7 +371,6 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan } QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); - QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation); QDpi ldpi = logicalDpi(); @@ -409,6 +408,8 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) m_availableGeometry = m_geometry & virtualAvailableGeometry; } free(workArea); + + QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), m_availableGeometry); } void QXcbScreen::updateRefreshRate() diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index aabcb84a08..1751eea990 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1825,6 +1825,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; const xcb_atom_t netWmStateAtom = atom(QXcbAtom::_NET_WM_STATE); const xcb_atom_t wmStateAtom = atom(QXcbAtom::WM_STATE); + const xcb_atom_t netWorkAreaAtom = atom(QXcbAtom::_NET_WORKAREA); if (event->atom == netWmStateAtom || event->atom == wmStateAtom) { if (propertyDeleted) @@ -1860,6 +1861,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev m_windowState = newState; } return; + } else if (event->atom == netWorkAreaAtom && event->window == m_screen->root()) { + m_screen->updateGeometry(event->time); } } -- cgit v1.2.3 From c6e271da6d1d972ad73a97871baafe57578a69a9 Mon Sep 17 00:00:00 2001 From: Martin Klapetek Date: Wed, 12 Mar 2014 12:07:43 +0100 Subject: QXcbWindow - inline the atom functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3a8f9efb7de21bf2301721edca49c9411c62eed0 Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbwindow.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1751eea990..d890398416 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1823,24 +1823,21 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev connection()->setTime(event->time); const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; - const xcb_atom_t netWmStateAtom = atom(QXcbAtom::_NET_WM_STATE); - const xcb_atom_t wmStateAtom = atom(QXcbAtom::WM_STATE); - const xcb_atom_t netWorkAreaAtom = atom(QXcbAtom::_NET_WORKAREA); - if (event->atom == netWmStateAtom || event->atom == wmStateAtom) { + if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { if (propertyDeleted) return; Qt::WindowState newState = Qt::WindowNoState; - if (event->atom == wmStateAtom) { // WM_STATE: Quick check for 'Minimize'. + if (event->atom == atom(QXcbAtom::_NET_WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. const xcb_get_property_cookie_t get_cookie = - xcb_get_property(xcb_connection(), 0, m_window, wmStateAtom, + xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ANY, 0, 1024); xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - if (reply && reply->format == 32 && reply->type == wmStateAtom) { + if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::_NET_WM_STATE)) { const quint32 *data = (const quint32 *)xcb_get_property_value(reply); if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0]) newState = Qt::WindowMinimized; @@ -1861,7 +1858,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev m_windowState = newState; } return; - } else if (event->atom == netWorkAreaAtom && event->window == m_screen->root()) { + } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && event->window == m_screen->root()) { m_screen->updateGeometry(event->time); } } -- cgit v1.2.3 From cc0636ea1eb34b654bd14ce840d1ffa5a07e44fe Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 7 Mar 2014 13:18:31 +0100 Subject: Remove level 4 compiler warnings from MSVC. Task-number: QTBUG-7233 Change-Id: I52067e3a22e98a62fd87415906e54a54ff2d6b49 Reviewed-by: Kurt Pattyn Reviewed-by: Oliver Wolff Reviewed-by: Joerg Bornemann Reviewed-by: Dave McClelland --- src/concurrent/qtconcurrentiteratekernel.h | 2 ++ src/corelib/global/qglobal.h | 3 +++ src/corelib/kernel/qmetatype.h | 4 ++++ src/corelib/kernel/qobject_impl.h | 2 ++ src/corelib/tools/qhash.h | 24 ++++++++++++++++-------- src/corelib/tools/qlist.h | 9 +++++++++ src/corelib/tools/qmap.h | 9 +++++++++ src/corelib/tools/qstring.h | 11 +++++++++++ src/corelib/tools/qstringbuilder.h | 8 ++++++++ src/corelib/tools/qvector.h | 9 +++++++++ 10 files changed, 73 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/concurrent/qtconcurrentiteratekernel.h b/src/concurrent/qtconcurrentiteratekernel.h index b47c30aef6..0969029e37 100644 --- a/src/concurrent/qtconcurrentiteratekernel.h +++ b/src/concurrent/qtconcurrentiteratekernel.h @@ -86,6 +86,8 @@ private: Median controlPartElapsed; Median userPartElapsed; int m_blockSize; + + Q_DISABLE_COPY(BlockSizeManager) }; template diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 0e5c4965f9..9b5d78b6fe 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -881,8 +881,11 @@ struct QForeachContainerBase {}; template class QForeachContainer : public QForeachContainerBase { + QForeachContainer &operator=(const QForeachContainer &) Q_DECL_EQ_DELETE; public: inline QForeachContainer(const T& t): c(t), brk(0), i(c.begin()), e(c.end()){} + QForeachContainer(const QForeachContainer &other) + : c(other.c), brk(other.brk), i(other.i), e(other.e) {} const T c; mutable int brk; mutable typename T::const_iterator i, e; diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 83801a20c5..5e354b3f41 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -771,9 +771,13 @@ struct VariantData , flags(flags_) { } + VariantData(const VariantData &other) + : metaTypeId(other.metaTypeId), data(other.data), flags(other.flags){} const int metaTypeId; const void *data; const uint flags; +private: + VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE; }; template diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index d2996e6e4d..aea9d41c67 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -132,6 +132,8 @@ namespace QtPrivate { inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, 0); } protected: ~QSlotObjectBase() {} + private: + Q_DISABLE_COPY(QSlotObjectBase) }; // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index d4bf8df442..40e501355c 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -52,6 +52,12 @@ #include #endif +#if defined(Q_CC_MSVC) +#pragma warning( push ) +#pragma warning( disable : 4311 ) // disable pointer truncation warning +#pragma warning( disable : 4127 ) // conditional expression is constant +#endif + QT_BEGIN_NAMESPACE class QBitArray; @@ -99,18 +105,10 @@ Q_CORE_EXPORT uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW; Q_CORE_EXPORT uint qt_hash(const QString &key) Q_DECL_NOTHROW; Q_CORE_EXPORT uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW; -#if defined(Q_CC_MSVC) -#pragma warning( push ) -#pragma warning( disable : 4311 ) // disable pointer truncation warning -#endif template inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW { return qHash(reinterpret_cast(key), seed); } -#if defined(Q_CC_MSVC) -#pragma warning( pop ) -#endif - template inline uint qHash(const T &t, uint seed) Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) { return (qHash(t) ^ seed); } @@ -218,6 +216,9 @@ struct QHashNode inline QHashNode(const Key &key0, const T &value0, uint hash, QHashNode *n) : next(n), h(hash), key(key0), value(value0) {} inline bool same_key(uint h0, const Key &key0) const { return h0 == h && key0 == key; } + +private: + Q_DISABLE_COPY(QHashNode) }; template @@ -228,6 +229,9 @@ struct QHashDummyNode const Key key; inline QHashDummyNode(const Key &key0, uint hash, QHashNode *n) : next(n), h(hash), key(key0) {} + +private: + Q_DISABLE_COPY(QHashDummyNode) }; @@ -1091,4 +1095,8 @@ Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash) QT_END_NAMESPACE +#if defined(Q_CC_MSVC) +#pragma warning( pop ) +#endif + #endif // QHASH_H diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 16f058b001..3a0d01aa8d 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -58,6 +58,11 @@ #include #include +#ifdef Q_CC_MSVC +#pragma warning( push ) +#pragma warning( disable : 4127 ) // "conditional expression is constant" +#endif + QT_BEGIN_NAMESPACE @@ -937,4 +942,8 @@ Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List) QT_END_NAMESPACE +#ifdef Q_CC_MSVC +#pragma warning( pop ) +#endif + #endif // QLIST_H diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index db0cd6a2d6..487039ccfb 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -260,6 +260,11 @@ QMapNode *QMapNode::copy(QMapData *d) const return n; } +#if defined(Q_CC_MSVC) +#pragma warning( push ) +#pragma warning( disable : 4127 ) // conditional expression is constant +#endif + template void QMapNode::destroySubTree() { @@ -275,6 +280,10 @@ void QMapNode::destroySubTree() } } +#if defined(Q_CC_MSVC) +#pragma warning( pop ) +#endif + template void QMapData::deleteNode(QMapNode *z) { diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 9063f59171..cf0726d831 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -870,6 +870,12 @@ inline QString QString::arg(const QString &a1, const QString &a2, const QString inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const { return section(QString(asep), astart, aend, aflags); } +#ifdef Q_CC_MSVC +// "conditional expression is constant" +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + inline int QString::toWCharArray(wchar_t *array) const { if (sizeof(wchar_t) == sizeof(QChar)) { @@ -878,6 +884,11 @@ inline int QString::toWCharArray(wchar_t *array) const } return toUcs4_helper(d->data(), size(), reinterpret_cast(array)); } + +#ifdef Q_CC_MSVC +#pragma warning(pop) +#endif + inline QString QString::fromWCharArray(const wchar_t *string, int size) { return sizeof(wchar_t) == sizeof(QChar) ? fromUtf16(reinterpret_cast(string), size) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index f0670999d7..befa40081c 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -143,12 +143,16 @@ class QStringBuilder : public QStringBuilderBase @@ -156,12 +160,16 @@ class QStringBuilder : public QStringBuilderBase::copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom) } } +#if defined(Q_CC_MSVC) +#pragma warning( push ) +#pragma warning( disable : 4127 ) // conditional expression is constant +#endif + template void QVector::destruct(T *from, T *to) { @@ -297,6 +302,10 @@ void QVector::destruct(T *from, T *to) } } +#if defined(Q_CC_MSVC) +#pragma warning( pop ) +#endif + template inline QVector::QVector(const QVector &v) { -- cgit v1.2.3 From 0b7beaaaf2384fae01ae403737450a59b2fcabac Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 12 Mar 2014 17:32:48 +0100 Subject: Fix rendering of grayscale antialiased FT fonts on QGLWidget QFontEngineFT::alphaMapForGlyph and QFontEngineFT::alphaRGBMapForGlyph has been broken since change#65694. They always fall back to using the path rendering of QFontEngine because we zero the scoped pointer just before testing it. To fix it we need to release the scope pointer after we are done using it. Change-Id: I8811c1f5261f286f2f3dd3c0f93c988ba0909669 Reviewed-by: Konstantin Ritt --- src/gui/text/qfontengine_ft.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 11e9ce6c02..fe38755ffd 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1934,8 +1934,6 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition) lockFace(); QScopedPointer glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono)); - if (cacheEnabled) - glyph.take(); if (!glyph || !glyph->data) { unlockFace(); return QFontEngine::alphaMapForGlyph(g); @@ -1960,6 +1958,8 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition) for (int y = 0; y < glyph->height; ++y) memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch); } + if (cacheEnabled) + glyph.take(); unlockFace(); return img; @@ -1973,8 +1973,6 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co lockFace(); QScopedPointer glyph(loadGlyphFor(g, subPixelPosition, Format_A32)); - if (cacheEnabled) - glyph.take(); if (!glyph || !glyph->data) { unlockFace(); return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); @@ -1982,6 +1980,9 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co QImage img(glyph->width, glyph->height, QImage::Format_RGB32); memcpy(img.bits(), glyph->data, 4 * glyph->width * glyph->height); + + if (cacheEnabled) + glyph.take(); unlockFace(); return img; -- cgit v1.2.3 From ffc8aac684e97bad1fb598883fa05ae66f7f1e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 12 Mar 2014 11:01:26 +0100 Subject: Fix high-dpi QGraphicsPixmapItem bounding rects. QGraphicsPixmapItem did not take the pixmaps devicePixelRatio into account when calculating the bounding rect. As a consequence, a 512x512@2x pixmap would get a 512x512 bounding size instead of the correct 256x256 bounding size. Task-number: QTBUG-37008 Change-Id: I266e418b7e5d92bf1d4c96bd9380a27708dc2b4a Reviewed-by: Gabriel de Dietrich Reviewed-by: Andreas Aardal Hanssen --- src/widgets/graphicsview/qgraphicsitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index 292b0419ca..f1b3d95f9c 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -9592,9 +9592,9 @@ QRectF QGraphicsPixmapItem::boundingRect() const return QRectF(); if (d->flags & ItemIsSelectable) { qreal pw = 1.0; - return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); + return QRectF(d->offset, d->pixmap.size() / d->pixmap.devicePixelRatio()).adjusted(-pw/2, -pw/2, pw/2, pw/2); } else { - return QRectF(d->offset, d->pixmap.size()); + return QRectF(d->offset, d->pixmap.size() / d->pixmap.devicePixelRatio()); } } -- cgit v1.2.3 From 8212e0cfad754d65146a21c95f38deaac8ffe8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 12 Mar 2014 09:41:07 +0100 Subject: Cocoa: Set "Stereo" OpenGL format option. Task-number: QTBUG-35548 Change-Id: I60b633ae44b8b4b353a7328eb0922b9301e1460c Reviewed-by: Sean Harmer --- src/platformsupport/cglconvenience/cglconvenience.mm | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/platformsupport/cglconvenience/cglconvenience.mm b/src/platformsupport/cglconvenience/cglconvenience.mm index 50c39a12e0..7379919588 100644 --- a/src/platformsupport/cglconvenience/cglconvenience.mm +++ b/src/platformsupport/cglconvenience/cglconvenience.mm @@ -121,6 +121,9 @@ void *qcgl_createNSOpenGLPixelFormat(const QSurfaceFormat &format) << NSOpenGLPFASamples << (NSOpenGLPixelFormatAttribute) format.samples(); } + if (format.stereo()) + attrs << NSOpenGLPFAStereo; + attrs << NSOpenGLPFAAllowOfflineRenderers; attrs << 0; -- cgit v1.2.3 From ac178eae4eb9f2647d07de2dfffa3c7ed18e2de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Mon, 17 Mar 2014 09:38:39 +0100 Subject: Fix Q_DECLARE_METATYPE macro The macro should stringify value of the given token not the token itself. Task-number: QTBUG-37547 Change-Id: I90f4fa613bd13d5a581828ab13f620b40dfd3593 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 5e354b3f41..c468c0b45d 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1706,7 +1706,8 @@ inline int qRegisterMetaTypeStreamOperators() } QT_END_NAMESPACE \ /**/ -#define Q_DECLARE_METATYPE(TYPE) \ +#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE) +#define Q_DECLARE_METATYPE_IMPL(TYPE) \ QT_BEGIN_NAMESPACE \ template <> \ struct QMetaTypeId< TYPE > \ -- cgit v1.2.3 From 2861a4d109989a626ed32b2f3be54b4d50c5c9c1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 12 Mar 2014 16:56:19 +0100 Subject: Fix no-opengl build with egl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable eglfs and similar plugins when opengl is not enabled. (but egl is present) GL-dependent parts of eglconvenience need to be skipped too. Task-number: QTBUG-37457 Change-Id: I44d49495241551bc7b1f565aa0b5ace9f310628e Reviewed-by: Thiago Macieira Reviewed-by: Jørgen Lind --- .../eglconvenience/eglconvenience.pri | 37 ++++++++++++---------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index c026ff5a4b..7600cc952b 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -1,30 +1,33 @@ contains(QT_CONFIG,egl) { HEADERS += \ $$PWD/qeglconvenience_p.h \ - $$PWD/qeglplatformcontext_p.h \ $$PWD/qeglpbuffer_p.h SOURCES += \ $$PWD/qeglconvenience.cpp \ - $$PWD/qeglplatformcontext.cpp \ $$PWD/qeglpbuffer.cpp - unix { - HEADERS += \ - $$PWD/qeglplatformcursor_p.h \ - $$PWD/qeglplatformwindow_p.h \ - $$PWD/qeglplatformscreen_p.h \ - $$PWD/qeglcompositor_p.h \ - $$PWD/qeglplatformbackingstore_p.h \ - $$PWD/qeglplatformintegration_p.h + contains(QT_CONFIG,opengl) { + HEADERS += $$PWD/qeglplatformcontext_p.h + SOURCES += $$PWD/qeglplatformcontext.cpp - SOURCES += \ - $$PWD/qeglplatformcursor.cpp \ - $$PWD/qeglplatformwindow.cpp \ - $$PWD/qeglplatformscreen.cpp \ - $$PWD/qeglcompositor.cpp \ - $$PWD/qeglplatformbackingstore.cpp \ - $$PWD/qeglplatformintegration.cpp + unix { + HEADERS += \ + $$PWD/qeglplatformcursor_p.h \ + $$PWD/qeglplatformwindow_p.h \ + $$PWD/qeglplatformscreen_p.h \ + $$PWD/qeglcompositor_p.h \ + $$PWD/qeglplatformbackingstore_p.h \ + $$PWD/qeglplatformintegration_p.h + + SOURCES += \ + $$PWD/qeglplatformcursor.cpp \ + $$PWD/qeglplatformwindow.cpp \ + $$PWD/qeglplatformscreen.cpp \ + $$PWD/qeglcompositor.cpp \ + $$PWD/qeglplatformbackingstore.cpp \ + $$PWD/qeglplatformintegration.cpp + } } # Avoid X11 header collision -- cgit v1.2.3 From cf56e066ada1029aa7e25bca99843a6b1fbc8f09 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 17 Mar 2014 11:57:16 +0100 Subject: Revert "Make OpenGL texture glyph cache use the right freetype glyphs" This reverts commit f78661b03cc1affcdd222be50b35d956edac4711. The reverted patch was working around that QFontEngineFT was using the poor QFontEngine fall back. That issue was fixed in commit 0b7beaaaf2384fae01ae403737450a59b2fcabac, and the work around is no longer needed. This also fixes a rare problem with the workaround when the fontengine and the glyph-cache do not share the same default glyph format which can happen with QRawFonts. Change-Id: I150f70a003b137c1d145f6f70cda568c85633e5c Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopengltextureglyphcache.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index 5844bf639c..3287bbb972 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -350,17 +350,7 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed return; } - QImage mask; - - if (m_current_fontengine->hasInternalCaching()) { - QImage *alphaMap = m_current_fontengine->lockedAlphaMapForGlyph(glyph, subPixelPosition, QFontEngine::Format_None); - if (!alphaMap || alphaMap->isNull()) - return; - mask = alphaMap->copy(); - m_current_fontengine->unlockAlphaMapForGlyph(); - } else { - mask = textureMapForGlyph(glyph, subPixelPosition); - } + QImage mask = textureMapForGlyph(glyph, subPixelPosition); const int maskWidth = mask.width(); const int maskHeight = mask.height(); -- cgit v1.2.3 From ad0163d088ace67aa1f94097ef917b8ff49324a6 Mon Sep 17 00:00:00 2001 From: John Layt Date: Sun, 26 Jan 2014 14:21:59 +0100 Subject: QPrinter - Add page metric tests Add more page metrics tests to expose the many bugs and inconsistencies in the page layout handling. No platform or pdf backend passes all these tests so they are skipped for now, but following commits will use the tests to ensure the re-write of the page layout handling fixes the many problems in a consistent way for all backends. Change-Id: Ic5b16aa08dfe2bd9a9191662fd2bbe6b913e15c9 Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprinter.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 496883f44b..9e9a0625d7 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -1024,6 +1024,9 @@ void QPrinter::setPageSize(PageSize newPageSize) Sets the paper size based on \a paperSize in \a unit. + Note that the paper size is defined in a portrait layout, regardless of + what the current printer orientation is set to. + \sa paperSize() */ @@ -1036,8 +1039,11 @@ void QPrinter::setPaperSize(const QSizeF &paperSize, QPrinter::Unit unit) } /*! - \reimp - */ + \reimp + + Note that the page size is defined in a portrait layout, regardless of + what the current printer orientation is set to. +*/ void QPrinter::setPageSizeMM(const QSizeF &size) { Q_D(QPrinter); @@ -1054,6 +1060,8 @@ void QPrinter::setPageSizeMM(const QSizeF &size) Returns the paper size in \a unit. + Note that the returned size reflects the current paper orientation. + \sa setPaperSize() */ -- cgit v1.2.3 From 87d802465b5acad91ea43fcebaa636bba2a1917a Mon Sep 17 00:00:00 2001 From: John Layt Date: Tue, 10 Dec 2013 20:23:07 +0100 Subject: QPageSize - Add new QPageSize class New QPageSize class to encapsulate paper sizes and names to ensure all sizes and conversions are consistent and match the Postscript standard sizes. Subsequent changes will use this class in the paged paint devices, paint engines, print engines, and print plugins to replace multiple inconsistent local implementations. [ChangeLog][QtGui][QPageSize] Added new QPageSize class to implement Adobe Postscript PPD standard page sizes. This class supports the standard page sizes, names and keys from the PPD standard, and provides convenient size and rect conversion methods. Change-Id: Ie2c8be0c3df0d29ac5da4cd9877ad41d0982633c Reviewed-by: Lars Knoll --- src/gui/painting/painting.pri | 2 + src/gui/painting/qpagedpaintdevice.h | 1 + src/gui/painting/qpagesize.cpp | 1876 ++++++++++++++++++++++++++++++++++ src/gui/painting/qpagesize.h | 310 ++++++ src/printsupport/kernel/qprinter.h | 1 + 5 files changed, 2190 insertions(+) create mode 100644 src/gui/painting/qpagesize.cpp create mode 100644 src/gui/painting/qpagesize.h (limited to 'src') diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 6bf80eddbd..8a51c3f379 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -19,6 +19,7 @@ HEADERS += \ painting/qoutlinemapper_p.h \ painting/qpagedpaintdevice.h \ painting/qpagedpaintdevice_p.h \ + painting/qpagesize.h \ painting/qpaintdevice.h \ painting/qpaintengine.h \ painting/qpaintengine_p.h \ @@ -66,6 +67,7 @@ SOURCES += \ painting/qmemrotate.cpp \ painting/qoutlinemapper.cpp \ painting/qpagedpaintdevice.cpp \ + painting/qpagesize.cpp \ painting/qpaintdevice.cpp \ painting/qpaintengine.cpp \ painting/qpaintengineex.cpp \ diff --git a/src/gui/painting/qpagedpaintdevice.h b/src/gui/painting/qpagedpaintdevice.h index d44a401184..a4e8ff1a48 100644 --- a/src/gui/painting/qpagedpaintdevice.h +++ b/src/gui/painting/qpagedpaintdevice.h @@ -60,6 +60,7 @@ public: virtual bool newPage() = 0; + // ### Qt6 Remove in favor of QPage::PageSize enum PageSize { A4, B5, Letter, Legal, Executive, A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1, B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E, diff --git a/src/gui/painting/qpagesize.cpp b/src/gui/painting/qpagesize.cpp new file mode 100644 index 0000000000..6a0e61e8a1 --- /dev/null +++ b/src/gui/painting/qpagesize.cpp @@ -0,0 +1,1876 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpagesize.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Define the Windows DMPAPER sizes for use in the look-up table +// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd319099.aspx + +enum WindowsDmPaper { + DMPAPER_NONE = 0, // Not a DMPAPER, use for sizes without a DMPAPER value + DMPAPER_LETTER = 1, + DMPAPER_LETTERSMALL = 2, + DMPAPER_TABLOID = 3, + DMPAPER_LEDGER = 4, + DMPAPER_LEGAL = 5, + DMPAPER_STATEMENT = 6, + DMPAPER_EXECUTIVE = 7, + DMPAPER_A3 = 8, + DMPAPER_A4 = 9, + DMPAPER_A4SMALL = 10, + DMPAPER_A5 = 11, + DMPAPER_B4 = 12, + DMPAPER_B5 = 13, + DMPAPER_FOLIO = 14, + DMPAPER_QUARTO = 15, + DMPAPER_10X14 = 16, + DMPAPER_11X17 = 17, + DMPAPER_NOTE = 18, + DMPAPER_ENV_9 = 19, + DMPAPER_ENV_10 = 20, + DMPAPER_ENV_11 = 21, + DMPAPER_ENV_12 = 22, + DMPAPER_ENV_14 = 23, + DMPAPER_CSHEET = 24, + DMPAPER_DSHEET = 25, + DMPAPER_ESHEET = 26, + DMPAPER_ENV_DL = 27, + DMPAPER_ENV_C5 = 28, + DMPAPER_ENV_C3 = 29, + DMPAPER_ENV_C4 = 30, + DMPAPER_ENV_C6 = 31, + DMPAPER_ENV_C65 = 32, + DMPAPER_ENV_B4 = 33, + DMPAPER_ENV_B5 = 34, + DMPAPER_ENV_B6 = 35, + DMPAPER_ENV_ITALY = 36, + DMPAPER_ENV_MONARCH = 37, + DMPAPER_ENV_PERSONAL = 38, + DMPAPER_FANFOLD_US = 39, + DMPAPER_FANFOLD_STD_GERMAN = 40, + DMPAPER_FANFOLD_LGL_GERMAN = 41, + DMPAPER_ISO_B4 = 42, + DMPAPER_JAPANESE_POSTCARD = 43, + DMPAPER_9X11 = 44, + DMPAPER_10X11 = 45, + DMPAPER_15X11 = 46, + DMPAPER_ENV_INVITE = 47, + DMPAPER_RESERVED_48 = 48, + DMPAPER_RESERVED_49 = 49, + DMPAPER_LETTER_EXTRA = 50, + DMPAPER_LEGAL_EXTRA = 51, + DMPAPER_TABLOID_EXTRA = 52, + DMPAPER_A4_EXTRA = 53, + DMPAPER_LETTER_TRANSVERSE = 54, + DMPAPER_A4_TRANSVERSE = 55, + DMPAPER_LETTER_EXTRA_TRANSVERSE = 56, + DMPAPER_A_PLUS = 57, + DMPAPER_B_PLUS = 58, + DMPAPER_LETTER_PLUS = 59, + DMPAPER_A4_PLUS = 60, + DMPAPER_A5_TRANSVERSE = 61, + DMPAPER_B5_TRANSVERSE = 62, + DMPAPER_A3_EXTRA = 63, + DMPAPER_A5_EXTRA = 64, + DMPAPER_B5_EXTRA = 65, + DMPAPER_A2 = 66, + DMPAPER_A3_TRANSVERSE = 67, + DMPAPER_A3_EXTRA_TRANSVERSE = 68, + DMPAPER_DBL_JAPANESE_POSTCARD = 69, + DMPAPER_A6 = 70, + DMPAPER_JENV_KAKU2 = 71, + DMPAPER_JENV_KAKU3 = 72, + DMPAPER_JENV_CHOU3 = 73, + DMPAPER_JENV_CHOU4 = 74, + DMPAPER_LETTER_ROTATED = 75, + DMPAPER_A3_ROTATED = 76, + DMPAPER_A4_ROTATED = 77, + DMPAPER_A5_ROTATED = 78, + DMPAPER_B4_JIS_ROTATED = 79, + DMPAPER_B5_JIS_ROTATED = 80, + DMPAPER_JAPANESE_POSTCARD_ROTATED = 81, + DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED = 82, + DMPAPER_A6_ROTATED = 83, + DMPAPER_JENV_KAKU2_ROTATED = 84, + DMPAPER_JENV_KAKU3_ROTATED = 85, + DMPAPER_JENV_CHOU3_ROTATED = 86, + DMPAPER_JENV_CHOU4_ROTATED = 87, + DMPAPER_B6_JIS = 88, + DMPAPER_B6_JIS_ROTATED = 89, + DMPAPER_12X11 = 90, + DMPAPER_JENV_YOU4 = 91, + DMPAPER_JENV_YOU4_ROTATED = 92, + DMPAPER_P16K = 93, + DMPAPER_P32K = 94, + DMPAPER_P32KBIG = 95, + DMPAPER_PENV_1 = 96, + DMPAPER_PENV_2 = 97, + DMPAPER_PENV_3 = 98, + DMPAPER_PENV_4 = 99, + DMPAPER_PENV_5 = 100, + DMPAPER_PENV_6 = 101, + DMPAPER_PENV_7 = 102, + DMPAPER_PENV_8 = 103, + DMPAPER_PENV_9 = 104, + DMPAPER_PENV_10 = 105, + DMPAPER_P16K_ROTATED = 106, + DMPAPER_P32K_ROTATED = 107, + DMPAPER_P32KBIG_ROTATED = 108, + DMPAPER_PENV_1_ROTATED = 109, + DMPAPER_PENV_2_ROTATED = 110, + DMPAPER_PENV_3_ROTATED = 111, + DMPAPER_PENV_4_ROTATED = 112, + DMPAPER_PENV_5_ROTATED = 113, + DMPAPER_PENV_6_ROTATED = 114, + DMPAPER_PENV_7_ROTATED = 115, + DMPAPER_PENV_8_ROTATED = 116, + DMPAPER_PENV_9_ROTATED = 117, + DMPAPER_PENV_10_ROTATED = 118, + DMPAPER_LAST = DMPAPER_PENV_10_ROTATED, + DMPAPER_USER = 256 +}; + +// Conversion table for historic page size values that we don't support. +// These are deprecated in PPD and strongly discouraged from being used, +// so convert them to usable page sizes to support older print devices. +// The paper source orientation will be handled in the QPrintMedia class, +// we're only concerned about the standard size in QPageSize. +// _ROTATED = 90 degrees or QPageLayout::Landscape +// _TRANSVERSE = 180 degrees or QPageLayout::ReversePortrait + +static const int qt_windowsConversion[][2] = { + {DMPAPER_11X17, DMPAPER_TABLOID}, // = DMPAPER_LEDGER rotated + {DMPAPER_A3_EXTRA_TRANSVERSE, DMPAPER_A3_EXTRA}, + {DMPAPER_A3_ROTATED, DMPAPER_A3}, + {DMPAPER_A3_TRANSVERSE, DMPAPER_A3}, + {DMPAPER_A4_ROTATED, DMPAPER_A4}, + {DMPAPER_A4_TRANSVERSE, DMPAPER_A4}, + {DMPAPER_A5_ROTATED, DMPAPER_A5}, + {DMPAPER_A5_TRANSVERSE, DMPAPER_A5}, + {DMPAPER_A6_ROTATED, DMPAPER_A6}, + {DMPAPER_B4_JIS_ROTATED, DMPAPER_B4}, + {DMPAPER_B5_JIS_ROTATED, DMPAPER_B5}, + {DMPAPER_B5_TRANSVERSE, DMPAPER_B5}, + {DMPAPER_B6_JIS_ROTATED, DMPAPER_B6_JIS}, + {DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED, DMPAPER_DBL_JAPANESE_POSTCARD}, + {DMPAPER_JAPANESE_POSTCARD_ROTATED, DMPAPER_JAPANESE_POSTCARD}, + {DMPAPER_JENV_CHOU3_ROTATED, DMPAPER_JENV_CHOU3}, + {DMPAPER_JENV_CHOU4_ROTATED, DMPAPER_JENV_CHOU4}, + {DMPAPER_JENV_KAKU2_ROTATED, DMPAPER_JENV_KAKU2}, + {DMPAPER_JENV_KAKU3_ROTATED, DMPAPER_JENV_KAKU3}, + {DMPAPER_JENV_YOU4_ROTATED, DMPAPER_JENV_YOU4}, + {DMPAPER_LETTER_EXTRA_TRANSVERSE, DMPAPER_LETTER_EXTRA}, + {DMPAPER_LETTER_ROTATED, DMPAPER_LETTER}, + {DMPAPER_LETTER_TRANSVERSE, DMPAPER_LETTER}, + {DMPAPER_P16K_ROTATED, DMPAPER_P16K}, + {DMPAPER_P32K_ROTATED, DMPAPER_P32K}, + {DMPAPER_P32KBIG_ROTATED, DMPAPER_P32KBIG}, + {DMPAPER_PENV_1_ROTATED, DMPAPER_PENV_1}, + {DMPAPER_PENV_2_ROTATED, DMPAPER_PENV_2}, + {DMPAPER_PENV_3_ROTATED, DMPAPER_PENV_3}, + {DMPAPER_PENV_4_ROTATED, DMPAPER_PENV_4}, + {DMPAPER_PENV_5_ROTATED, DMPAPER_PENV_5}, + {DMPAPER_PENV_6_ROTATED, DMPAPER_PENV_6}, + {DMPAPER_PENV_7_ROTATED, DMPAPER_PENV_7}, + {DMPAPER_PENV_8_ROTATED, DMPAPER_PENV_8}, + {DMPAPER_PENV_9_ROTATED, DMPAPER_PENV_9}, + {DMPAPER_PENV_10_ROTATED, DMPAPER_PENV_10} // Is = DMPAPER_LAST, use as loop terminator +}; + +static const int windowsConversionCount = int(sizeof(qt_windowsConversion) / sizeof(qt_windowsConversion[0])); + +// Standard sizes data +struct StandardPageSize { + QPageSize::PageSizeId id; + int windowsId; // Windows DMPAPER value + QPageSize::Unit definitionUnits; // Standard definition size, e.g. ISO uses mm, ANSI uses inches + int widthPoints; + int heightPoints; + qreal widthMillimeters; + qreal heightMillimeters; + qreal widthInches; + qreal heightInches; + const char *mediaOption; // PPD standard mediaOption ID +}; + +// Standard page sizes taken from the Postscript PPD Standard v4.3 +// See http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf +// Excludes all Transverse and Rotated sizes +// NB! This table needs to be in sync with QPageSize::PageSizeId +static const StandardPageSize qt_pageSizes[] = { + + // Existing Qt sizes including ISO, US, ANSI and other standards + {QPageSize::A4 , DMPAPER_A4 , QPageSize::Millimeter, 595, 842, 210 , 297 , 8.27, 11.69, "A4"}, + {QPageSize::B5 , DMPAPER_NONE , QPageSize::Millimeter, 499, 709, 176 , 250 , 6.9 , 9.8 , "ISOB5"}, + {QPageSize::Letter , DMPAPER_LETTER , QPageSize::Inch , 612, 792, 215.9, 279.4, 8.5 , 11 , "Letter"}, + {QPageSize::Legal , DMPAPER_LEGAL , QPageSize::Inch , 612, 1008, 215.9, 355.6, 8.5 , 14 , "Legal"}, + {QPageSize::Executive , DMPAPER_NONE , QPageSize::Inch , 540, 720, 190.5, 254 , 7.5 , 10 , "Executive.7.5x10in"}, // Qt size differs from Postscript / Windows + {QPageSize::A0 , DMPAPER_NONE , QPageSize::Millimeter, 2384, 3370, 841 , 1189 , 33.11, 46.81, "A0"}, + {QPageSize::A1 , DMPAPER_NONE , QPageSize::Millimeter, 1684, 2384, 594 , 841 , 23.39, 33.11, "A1"}, + {QPageSize::A2 , DMPAPER_A2 , QPageSize::Millimeter, 1191, 1684, 420 , 594 , 16.54, 23.39, "A2"}, + {QPageSize::A3 , DMPAPER_A3 , QPageSize::Millimeter, 842, 1191, 297 , 420 , 11.69, 16.54, "A3"}, + {QPageSize::A5 , DMPAPER_A5 , QPageSize::Millimeter, 420, 595, 148 , 210 , 5.83, 8.27, "A5"}, + {QPageSize::A6 , DMPAPER_A6 , QPageSize::Millimeter, 297, 420, 105 , 148 , 4.13, 5.83, "A6"}, + {QPageSize::A7 , DMPAPER_NONE , QPageSize::Millimeter, 210, 297, 74 , 105 , 2.91, 4.13, "A7"}, + {QPageSize::A8 , DMPAPER_NONE , QPageSize::Millimeter, 148, 210, 52 , 74 , 2.05, 2.91, "A8"}, + {QPageSize::A9 , DMPAPER_NONE , QPageSize::Millimeter, 105, 148, 37 , 52 , 1.46, 2.05, "A9"}, + {QPageSize::B0 , DMPAPER_NONE , QPageSize::Millimeter, 2835, 4008, 1000 , 1414 , 39.37, 55.67, "ISOB0"}, + {QPageSize::B1 , DMPAPER_NONE , QPageSize::Millimeter, 2004, 2835, 707 , 1000 , 27.83, 39.37, "ISOB1"}, + {QPageSize::B10 , DMPAPER_NONE , QPageSize::Millimeter, 88, 125, 31 , 44 , 1.22, 1.73, "ISOB10"}, + {QPageSize::B2 , DMPAPER_NONE , QPageSize::Millimeter, 1417, 2004, 500 , 707 , 19.68, 27.83, "ISOB2"}, + {QPageSize::B3 , DMPAPER_NONE , QPageSize::Millimeter, 1001, 1417, 353 , 500 , 13.9 , 19.68, "ISOB3"}, + {QPageSize::B4 , DMPAPER_ISO_B4 , QPageSize::Millimeter, 709, 1001, 250 , 353 , 9.84, 13.9 , "ISOB4"}, + {QPageSize::B6 , DMPAPER_NONE , QPageSize::Millimeter, 354, 499, 125 , 176 , 4.92, 6.93, "ISOB6"}, + {QPageSize::B7 , DMPAPER_NONE , QPageSize::Millimeter, 249, 354, 88 , 125 , 3.46, 4.92, "ISOB7"}, + {QPageSize::B8 , DMPAPER_NONE , QPageSize::Millimeter, 176, 249, 62 , 88 , 2.44, 3.46, "ISOB8"}, + {QPageSize::B9 , DMPAPER_NONE , QPageSize::Millimeter, 125, 176, 44 , 62 , 1.73, 2.44, "ISOB9"}, + {QPageSize::C5E , DMPAPER_ENV_C5 , QPageSize::Millimeter, 459, 649, 162 , 229 , 6.38, 9.02, "EnvC5"}, + {QPageSize::Comm10E , DMPAPER_ENV_10 , QPageSize::Inch , 297, 684, 104.8, 241.3, 4.12, 9.5 , "Env10"}, + {QPageSize::DLE , DMPAPER_ENV_DL , QPageSize::Millimeter, 312, 624, 110 , 220 , 4.33, 8.66, "EnvDL"}, + {QPageSize::Folio , DMPAPER_NONE , QPageSize::Millimeter, 595, 935, 210 , 330 , 8.27, 13 , "Folio"}, + {QPageSize::Ledger , DMPAPER_LEDGER , QPageSize::Inch , 1224, 792, 431.8, 279.4, 17 , 11 , "Ledger"}, + {QPageSize::Tabloid , DMPAPER_TABLOID , QPageSize::Inch , 792, 1224, 279.4, 431.8, 11 , 17 , "Tabloid"}, + {QPageSize::Custom , DMPAPER_USER , QPageSize::Millimeter, -1, -1, -1. , -1 , -1 , -1 , "Custom"}, // Special case to keep in sync with QPageSize::PageSizeId + + // ISO Standard Sizes + {QPageSize::A10 , DMPAPER_NONE , QPageSize::Millimeter, 73, 105, 26 , 37 , 1.02, 1.46, "A10"}, + {QPageSize::A3Extra , DMPAPER_A3_EXTRA , QPageSize::Millimeter, 913, 1262, 322 , 445 , 12.67, 17.52, "A3Extra"}, + {QPageSize::A4Extra , DMPAPER_A4_EXTRA , QPageSize::Millimeter, 667, 914, 235.5, 322.3, 9.27, 12.69, "A4Extra"}, + {QPageSize::A4Plus , DMPAPER_A4_PLUS , QPageSize::Millimeter, 595, 936, 210 , 330 , 8.27, 13 , "A4Plus"}, + {QPageSize::A4Small , DMPAPER_A4SMALL , QPageSize::Millimeter, 595, 842, 210 , 297 , 8.27, 11.69, "A4Small"}, + {QPageSize::A5Extra , DMPAPER_A5_EXTRA , QPageSize::Millimeter, 492, 668, 174 , 235 , 6.85, 9.25, "A5Extra"}, + {QPageSize::B5Extra , DMPAPER_B5_EXTRA , QPageSize::Millimeter, 570, 782, 201 , 276 , 7.9 , 10.8 , "ISOB5Extra"}, + + // JIS Standard Sizes + {QPageSize::JisB0 , DMPAPER_NONE , QPageSize::Millimeter, 2920, 4127, 1030 , 1456 , 40.55, 57.32, "B0"}, + {QPageSize::JisB1 , DMPAPER_NONE , QPageSize::Millimeter, 2064, 2920, 728 , 1030 , 28.66, 40.55, "B1"}, + {QPageSize::JisB2 , DMPAPER_NONE , QPageSize::Millimeter, 1460, 2064, 515 , 728 , 20.28, 28.66, "B2"}, + {QPageSize::JisB3 , DMPAPER_NONE , QPageSize::Millimeter, 1032, 1460, 364 , 515 , 14.33, 20.28, "B3"}, + {QPageSize::JisB4 , DMPAPER_B4 , QPageSize::Millimeter, 729, 1032, 257 , 364 , 10.12, 14.33, "B4"}, + {QPageSize::JisB5 , DMPAPER_B5 , QPageSize::Millimeter, 516, 729, 182 , 257 , 7.17, 10.12, "B5"}, + {QPageSize::JisB6 , DMPAPER_B6_JIS , QPageSize::Millimeter, 363, 516, 128 , 182 , 5.04, 7.17, "B6"}, + {QPageSize::JisB7 , DMPAPER_NONE , QPageSize::Millimeter, 258, 363, 91 , 128 , 3.58, 5.04, "B7"}, + {QPageSize::JisB8 , DMPAPER_NONE , QPageSize::Millimeter, 181, 258, 64 , 91 , 2.52, 3.58, "B8"}, + {QPageSize::JisB9 , DMPAPER_NONE , QPageSize::Millimeter, 127, 181, 45 , 64 , 1.77, 2.52, "B9"}, + {QPageSize::JisB10 , DMPAPER_NONE , QPageSize::Millimeter, 91, 127, 32 , 45 , 1.26, 1.77, "B10"}, + + // ANSI / US Standard sizes + {QPageSize::AnsiC , DMPAPER_NONE , QPageSize::Inch , 1224, 1584, 431.8, 558.8, 17 , 22 , "AnsiC"}, + {QPageSize::AnsiD , DMPAPER_NONE , QPageSize::Inch , 1584, 2448, 558.8, 863.6, 22 , 34 , "AnsiD"}, + {QPageSize::AnsiE , DMPAPER_NONE , QPageSize::Inch , 2448, 3168, 863.6, 1118 , 34 , 44 , "AnsiE"}, + {QPageSize::LegalExtra , DMPAPER_LEGAL_EXTRA , QPageSize::Inch , 684, 1080, 241.3, 381 , 9.5 , 15 , "LegalExtra"}, + {QPageSize::LetterExtra , DMPAPER_LETTER_EXTRA , QPageSize::Inch , 684, 864, 241.3, 304.8, 9.5 , 12 , "LetterExtra"}, + {QPageSize::LetterPlus , DMPAPER_LETTER_PLUS , QPageSize::Inch , 612, 914, 215.9, 322.3, 8.5 , 12.69, "LetterPlus"}, + {QPageSize::LetterSmall , DMPAPER_LETTERSMALL , QPageSize::Inch , 612, 792, 215.9, 279.4, 8.5 , 11 , "LetterSmall"}, + {QPageSize::TabloidExtra , DMPAPER_TABLOID_EXTRA , QPageSize::Inch , 864, 1296, 304.8, 457.2, 12 , 18 , "TabloidExtra"}, + + // Architectural sizes + {QPageSize::ArchA , DMPAPER_NONE , QPageSize::Inch , 648, 864, 228.6, 304.8, 9 , 12 , "ARCHA"}, + {QPageSize::ArchB , DMPAPER_NONE , QPageSize::Inch , 864, 1296, 304.8, 457.2, 12 , 18 , "ARCHB"}, + {QPageSize::ArchC , DMPAPER_CSHEET , QPageSize::Inch , 1296, 1728, 457.2, 609.6, 18 , 24 , "ARCHC"}, + {QPageSize::ArchD , DMPAPER_DSHEET , QPageSize::Inch , 1728, 2592, 609.6, 914.4, 24 , 36 , "ARCHD"}, + {QPageSize::ArchE , DMPAPER_ESHEET , QPageSize::Inch , 2592, 3456, 914.4, 1219 , 36 , 48 , "ARCHE"}, + + // Inch-based Sizes + {QPageSize::Imperial7x9 , DMPAPER_NONE , QPageSize::Inch , 504, 648, 177.8, 228.6, 7 , 9 , "7x9"}, + {QPageSize::Imperial8x10 , DMPAPER_NONE , QPageSize::Inch , 576, 720, 203.2, 254 , 8 , 10 , "8x10"}, + {QPageSize::Imperial9x11 , DMPAPER_9X11 , QPageSize::Inch , 648, 792, 228.6, 279.4, 9 , 11 , "9x11"}, + {QPageSize::Imperial9x12 , DMPAPER_NONE , QPageSize::Inch , 648, 864, 228.6, 304.8, 9 , 12 , "9x12"}, + {QPageSize::Imperial10x11 , DMPAPER_10X11 , QPageSize::Inch , 720, 792, 254 , 279.4, 10 , 11 , "10x11"}, + {QPageSize::Imperial10x13 , DMPAPER_NONE , QPageSize::Inch , 720, 936, 254 , 330.2, 10 , 13 , "10x13"}, + {QPageSize::Imperial10x14 , DMPAPER_10X14 , QPageSize::Inch , 720, 1008, 254 , 355.6, 10 , 14 , "10x14"}, + {QPageSize::Imperial12x11 , DMPAPER_12X11 , QPageSize::Inch , 864, 792, 304.8, 279.4, 12 , 11 , "12x11"}, + {QPageSize::Imperial15x11 , DMPAPER_15X11 , QPageSize::Inch , 1080, 792, 381 , 279.4, 15 , 11 , "15x11"}, + + // Other Page Sizes + {QPageSize::ExecutiveStandard , DMPAPER_EXECUTIVE , QPageSize::Inch , 522, 756, 184.2, 266.7, 7.25, 10.5 , "Executive"}, // Qt size differs from Postscript / Windows + {QPageSize::Note , DMPAPER_NOTE , QPageSize::Inch , 612, 792, 215.9, 279.4, 8.5 , 11 , "Note"}, + {QPageSize::Quarto , DMPAPER_QUARTO , QPageSize::Inch , 610, 780, 215.9, 275.1, 8.5 , 10.83, "Quarto"}, + {QPageSize::Statement , DMPAPER_STATEMENT , QPageSize::Inch , 396, 612, 139.7, 215.9, 5.5 , 8.5 , "Statement"}, + {QPageSize::SuperA , DMPAPER_A_PLUS , QPageSize::Millimeter, 643, 1009, 227 , 356 , 8.94, 14 , "SuperA"}, + {QPageSize::SuperB , DMPAPER_B_PLUS , QPageSize::Millimeter, 864, 1380, 305 , 487 , 12 , 19.17, "SuperB"}, + {QPageSize::Postcard , DMPAPER_JAPANESE_POSTCARD , QPageSize::Millimeter, 284, 419, 100 , 148 , 3.94, 5.83, "Postcard"}, + {QPageSize::DoublePostcard , DMPAPER_DBL_JAPANESE_POSTCARD, QPageSize::Millimeter, 567, 419, 200 , 148 , 7.87, 5.83, "DoublePostcard"}, + {QPageSize::Prc16K , DMPAPER_P16K , QPageSize::Millimeter, 414, 610, 146 , 215 , 5.75, 8.5 , "PRC16K"}, + {QPageSize::Prc32K , DMPAPER_P32K , QPageSize::Millimeter, 275, 428, 97 , 151 , 3.82, 5.95, "PRC32K"}, + {QPageSize::Prc32KBig , DMPAPER_P32KBIG , QPageSize::Millimeter, 275, 428, 97 , 151 , 3.82, 5.95, "PRC32KBig"}, + + // Fan Fold Sizes + {QPageSize::FanFoldUS , DMPAPER_FANFOLD_US , QPageSize::Inch , 1071, 792, 377.8, 279.4, 14.875, 11 , "FanFoldUS"}, + {QPageSize::FanFoldGerman , DMPAPER_FANFOLD_STD_GERMAN , QPageSize::Inch , 612, 864, 215.9, 304.8, 8.5 , 12 , "FanFoldGerman"}, + {QPageSize::FanFoldGermanLegal, DMPAPER_FANFOLD_LGL_GERMAN , QPageSize::Inch , 612, 936, 215.9, 330 , 8.5 , 13 , "FanFoldGermanLegal"}, + + // ISO Envelopes + {QPageSize::EnvelopeB4 , DMPAPER_ENV_B4 , QPageSize::Millimeter, 708, 1001, 250 , 353 , 9.84, 13.9 , "EnvISOB4"}, + {QPageSize::EnvelopeB5 , DMPAPER_ENV_B5 , QPageSize::Millimeter, 499, 709, 176 , 250 , 6.9 , 9.8 , "EnvISOB5"}, + {QPageSize::EnvelopeB6 , DMPAPER_ENV_B6 , QPageSize::Millimeter, 499, 354, 176 , 125 , 6.9 , 4.9 , "EnvISOB6"}, + {QPageSize::EnvelopeC0 , DMPAPER_NONE , QPageSize::Millimeter, 2599, 3676, 917 , 1297 , 36.1 , 51.06, "EnvC0"}, + {QPageSize::EnvelopeC1 , DMPAPER_NONE , QPageSize::Millimeter, 1837, 2599, 648 , 917 , 25.51, 36.1 , "EnvC1"}, + {QPageSize::EnvelopeC2 , DMPAPER_NONE , QPageSize::Millimeter, 1298, 1837, 458 , 648 , 18.03, 25.51, "EnvC2"}, + {QPageSize::EnvelopeC3 , DMPAPER_ENV_C3 , QPageSize::Millimeter, 918, 1296, 324 , 458 , 12.75, 18.03, "EnvC3"}, + {QPageSize::EnvelopeC4 , DMPAPER_ENV_C4 , QPageSize::Millimeter, 649, 918, 229 , 324 , 9.02, 12.75, "EnvC4"}, + {QPageSize::EnvelopeC6 , DMPAPER_ENV_C6 , QPageSize::Millimeter, 323, 459, 114 , 162 , 4.49, 6.38, "EnvC6"}, + {QPageSize::EnvelopeC65 , DMPAPER_ENV_C65 , QPageSize::Millimeter, 324, 648, 114 , 229 , 4.5 , 9 , "EnvC65"}, + {QPageSize::EnvelopeC7 , DMPAPER_NONE , QPageSize::Millimeter, 230, 323, 81 , 114 , 3.19, 4.49, "EnvC7"}, + + // US Envelopes + {QPageSize::Envelope9 , DMPAPER_ENV_9 , QPageSize::Inch , 279, 639, 98.4, 225.4, 3.875, 8.875, "Env9"}, + {QPageSize::Envelope11 , DMPAPER_ENV_11 , QPageSize::Inch , 324, 747, 114.3, 263.5, 4.5 , 10.375, "Env11"}, + {QPageSize::Envelope12 , DMPAPER_ENV_12 , QPageSize::Inch , 342, 792, 120.7, 279.4, 4.75, 11 , "Env12"}, + {QPageSize::Envelope14 , DMPAPER_ENV_14 , QPageSize::Inch , 360, 828, 127 , 292.1, 5 , 11.5 , "Env14"}, + {QPageSize::EnvelopeMonarch , DMPAPER_ENV_MONARCH , QPageSize::Inch , 279, 540, 98.43, 190.5, 3.875, 7.5 , "EnvMonarch"}, + {QPageSize::EnvelopePersonal , DMPAPER_ENV_PERSONAL , QPageSize::Inch , 261, 468, 92.08, 165.1, 3.625, 6.5 , "EnvPersonal"}, + + // Other Envelopes + {QPageSize::EnvelopeChou3 , DMPAPER_JENV_CHOU3 , QPageSize::Millimeter, 340, 666, 120 , 235 , 4.72, 9.25, "EnvChou3"}, + {QPageSize::EnvelopeChou4 , DMPAPER_JENV_CHOU4 , QPageSize::Millimeter, 255, 581, 90 , 205 , 3.54, 8 , "EnvChou4"}, + {QPageSize::EnvelopeInvite , DMPAPER_ENV_INVITE , QPageSize::Millimeter, 624, 624, 220 , 220 , 8.66, 8.66, "EnvInvite"}, + {QPageSize::EnvelopeItalian , DMPAPER_ENV_ITALY , QPageSize::Millimeter, 312, 652, 110 , 230 , 4.33, 9 , "EnvItalian"}, + {QPageSize::EnvelopeKaku2 , DMPAPER_JENV_KAKU2 , QPageSize::Millimeter, 680, 941, 240 , 332 , 9.45, 13 , "EnvKaku2"}, + {QPageSize::EnvelopeKaku3 , DMPAPER_JENV_KAKU3 , QPageSize::Millimeter, 612, 785, 216 , 277 , 8.5 , 10.9 , "EnvKaku3"}, + {QPageSize::EnvelopePrc1 , DMPAPER_PENV_1 , QPageSize::Millimeter, 289, 468, 102 , 165 , 4 , 6.5 , "EnvPRC1"}, + {QPageSize::EnvelopePrc2 , DMPAPER_PENV_2 , QPageSize::Millimeter, 289, 499, 102 , 176 , 4 , 6.9 , "EnvPRC2"}, + {QPageSize::EnvelopePrc3 , DMPAPER_PENV_3 , QPageSize::Millimeter, 354, 499, 125 , 176 , 4.9 , 6.9 , "EnvPRC3"}, + {QPageSize::EnvelopePrc4 , DMPAPER_PENV_4 , QPageSize::Millimeter, 312, 590, 110 , 208 , 4.33, 8.2 , "EnvPRC4"}, + {QPageSize::EnvelopePrc5 , DMPAPER_PENV_5 , QPageSize::Millimeter, 312, 624, 110 , 220 , 4.33, 8.66, "EnvPRC5"}, + {QPageSize::EnvelopePrc6 , DMPAPER_PENV_6 , QPageSize::Millimeter, 340, 652, 120 , 230 , 4.7 , 9 , "EnvPRC6"}, + {QPageSize::EnvelopePrc7 , DMPAPER_PENV_7 , QPageSize::Millimeter, 454, 652, 160 , 230 , 6.3 , 9 , "EnvPRC7"}, + {QPageSize::EnvelopePrc8 , DMPAPER_PENV_8 , QPageSize::Millimeter, 340, 876, 120 , 309 , 4.7 , 12.2 , "EnvPRC8"}, + {QPageSize::EnvelopePrc9 , DMPAPER_PENV_9 , QPageSize::Millimeter, 649, 918, 229 , 324 , 9 , 12.75, "EnvPRC9"}, + {QPageSize::EnvelopePrc10 , DMPAPER_PENV_10 , QPageSize::Millimeter, 918, 1298, 324 , 458 , 12.75, 18 , "EnvPRC10"}, + {QPageSize::EnvelopeYou4 , DMPAPER_JENV_YOU4 , QPageSize::Millimeter, 298, 666, 105 , 235 , 4.13, 9.25, "EnvYou4"} +}; + +static const int pageSizesCount = int(sizeof(qt_pageSizes) / sizeof(qt_pageSizes[0])); + +// Return key name for PageSize +static QString qt_keyForPageSizeId(QPageSize::PageSizeId id) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + return QString::fromLatin1(qt_pageSizes[id].mediaOption); +} + +// Return id name for PPD Key +static QPageSize::PageSizeId qt_idForPpdKey(const QString &ppdKey, QSize *match = 0) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + if (ppdKey.isEmpty()) + return QPageSize::Custom; + QString key = ppdKey; + // Remove any Rotated or Tranverse modifiers + if (key.endsWith(QStringLiteral("Rotated"))) + key.chop(7); + else if (key.endsWith(QStringLiteral(".Transverse"))) + key.chop(11); + for (int i = 0; i <= int(QPageSize::LastPageSize); ++i) { + if (QLatin1String(qt_pageSizes[i].mediaOption) == key) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + return QPageSize::Custom; +} + +// Return id name for Windows ID +static QPageSize::PageSizeId qt_idForWindowsID(int windowsId, QSize *match = 0) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + // If outside known values then is Custom + if (windowsId <= DMPAPER_NONE || windowsId > DMPAPER_LAST) + return QPageSize::Custom; + // Check if one of the unsupported values, convert to valid value if is + for (int i = 0; i < windowsConversionCount; ++i) { + if (qt_windowsConversion[i][0] == windowsId) { + windowsId = qt_windowsConversion[i][1]; + break; + } + } + // Look for the value in our supported size table + for (int i = 0; i <= int(QPageSize::LastPageSize); ++i) { + if (qt_pageSizes[i].windowsId == windowsId) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + // Otherwise is Custom + return QPageSize::Custom; +} + +// Return key name for custom size +static QString qt_keyForCustomSize(const QSizeF &size, QPageSize::Unit units) +{ + // PPD custom format + QString key = QStringLiteral("Custom.%1x%2%3"); + QString abbrev; + switch (units) { + case QPageSize::Millimeter: + abbrev = QStringLiteral("mm"); + break; + case QPageSize::Point: + break; + case QPageSize::Inch: + abbrev = QStringLiteral("in"); + break; + case QPageSize::Pica: + abbrev = QStringLiteral("pc"); + break; + case QPageSize::Didot: + abbrev = QStringLiteral("DD"); + break; + case QPageSize::Cicero: + abbrev = QStringLiteral("CC"); + break; + } + // Assumes size is already max 2 decimal places + return key.arg(size.width()).arg(size.height()).arg(abbrev); +} + +// Return localized name for custom size +static QString qt_nameForCustomSize(const QSizeF &size, QPageSize::Unit units) +{ + QString name; + switch (units) { + case QPageSize::Millimeter: + //: Custom size name in millimeters + name = QCoreApplication::translate("QPageSize", "Custom (%1mm x %2mm)"); + break; + case QPageSize::Point: + //: Custom size name in points + name = QCoreApplication::translate("QPageSize", "Custom (%1pt x %2pt)"); + break; + case QPageSize::Inch: + //: Custom size name in inches + name = QCoreApplication::translate("QPageSize", "Custom (%1in x %2in)"); + break; + case QPageSize::Pica: + //: Custom size name in picas + name = QCoreApplication::translate("QPageSize", "Custom (%1pc x %2pc)"); + break; + case QPageSize::Didot: + //: Custom size name in didots + name = QCoreApplication::translate("QPageSize", "Custom (%1DD x %2DD)"); + break; + case QPageSize::Cicero: + //: Custom size name in ciceros + name = QCoreApplication::translate("QPageSize", "Custom (%1CC x %2CC)"); + break; + } + // Assumes size is already max 2 decimal places + return name.arg(size.width()).arg(size.height()); +} + +// Multiplier for converting units to points. +static qreal qt_pointMultiplier(QPageSize::Unit unit) +{ + switch (unit) { + case QPageSize::Millimeter: + return 2.83464566929; + case QPageSize::Point: + return 1.0; + case QPageSize::Inch: + return 72.0; + case QPageSize::Pica: + return 12; + case QPageSize::Didot: + return 1.065826771; + case QPageSize::Cicero: + return 12.789921252; + } + return 1.0; +} + +// Multiplier for converting pixels to points. +Q_GUI_EXPORT qreal qt_pixelMultiplier(int resolution) +{ + return resolution <= 0 ? 1.0 : 72.0 / resolution; +} + +static QSizeF qt_definitionSize(QPageSize::PageSizeId pageSizeId) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + QPageSize::Unit units = qt_pageSizes[pageSizeId].definitionUnits; + if (units == QPageSize::Millimeter) + return QSizeF(qt_pageSizes[pageSizeId].widthMillimeters, qt_pageSizes[pageSizeId].heightMillimeters); + Q_ASSERT(units == QPageSize::Inch); // We currently only support definitions in mm or inches + return QSizeF(qt_pageSizes[pageSizeId].widthInches, qt_pageSizes[pageSizeId].heightInches); +} + +static QSizeF qt_convertUnits(const QSizeF &size, QPageSize::Unit fromUnits, QPageSize::Unit toUnits) +{ + if (!size.isValid()) + return QSizeF(); + + // If the units are the same or the size is 0, then don't need to convert + if (fromUnits == toUnits || (qFuzzyIsNull(size.width()) && qFuzzyIsNull(size.height()))) + return size; + + QSizeF newSize = size; + // First convert to points + if (fromUnits != QPageSize::Point) { + const qreal multiplier = qt_pointMultiplier(fromUnits); + newSize = newSize * multiplier; + } + // Then convert from points to required units + const qreal multiplier = qt_pointMultiplier(toUnits); + // Try force to 2 decimal places for consistency + const int width = qRound(newSize.width() * 100 / multiplier); + const int height = qRound(newSize.height() * 100 / multiplier); + return QSizeF(width / 100.0, height / 100.0); +} + +static QSize qt_convertUnitsToPoints(const QSizeF &size, QPageSize::Unit units) +{ + if (!size.isValid()) + return QSize(); + return QSizeF(size * qt_pointMultiplier(units)).toSize(); +} + +static QSize qt_convertPointsToPixels(const QSize &size, int resolution) +{ + if (!size.isValid() || resolution <= 0) + return QSize(); + const qreal multiplier = qt_pixelMultiplier(resolution); + return QSize(qRound(size.width() / multiplier), qRound(size.height() / multiplier)); +} + +static QSizeF qt_convertPointsToUnits(const QSize &size, QPageSize::Unit units) +{ + if (!size.isValid()) + return QSizeF(); + const qreal multiplier = qt_pointMultiplier(units); + // Try force to 2 decimal places for consistency + const int width = qRound(size.width() * 100 / multiplier); + const int height = qRound(size.height() * 100 / multiplier); + return QSizeF(width / 100.0, height / 100.0); +} + +static QSizeF qt_unitSize(QPageSize::PageSizeId pageSizeId, QPageSize::Unit units) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + switch (units) { + case QPageSize::Millimeter: + return QSizeF(qt_pageSizes[pageSizeId].widthMillimeters, qt_pageSizes[pageSizeId].heightMillimeters); + case QPageSize::Point: + return QSizeF(qt_pageSizes[pageSizeId].widthPoints, qt_pageSizes[pageSizeId].heightPoints); + case QPageSize::Inch: + return QSizeF(qt_pageSizes[pageSizeId].widthInches, qt_pageSizes[pageSizeId].heightInches); + case QPageSize::Pica: + case QPageSize::Didot: + case QPageSize::Cicero: + return qt_convertPointsToUnits(QSize(qt_pageSizes[pageSizeId].widthPoints, + qt_pageSizes[pageSizeId].heightPoints), units); + } + return QSizeF(); +} + +// Find matching standard page size for point size +static QPageSize::PageSizeId qt_idForPointSize(const QSize &size, QPageSize::SizeMatchPolicy matchPolicy, QSize *match) +{ + if (!size.isValid()) + return QPageSize::Custom; + + // Try exact match in portrait layout + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + for (int i = 0; i <= int(QPageSize::LastPageSize); ++i) { + if (size.width() == qt_pageSizes[i].widthPoints && size.height() == qt_pageSizes[i].heightPoints) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + + // If no exact match only try fuzzy if asked + if (matchPolicy != QPageSize::ExactMatch) { + // Set up the fuzzy tolerance + // TODO Use ISO standard tolerance based on page size? + const int tolerance = 3; // = approx 1mm + const int minWidth = size.width() - tolerance; + const int maxWidth = size.width() + tolerance; + const int minHeight = size.height() - tolerance; + const int maxHeight = size.height() + tolerance; + + // First try fuzzy match in portrait layout + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + const int width = qt_pageSizes[i].widthPoints; + const int height = qt_pageSizes[i].heightPoints; + if (width >= minWidth && width <= maxWidth && height >= minHeight && height <= maxHeight) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + + // If FuzzyOrientationMatch then try rotated sizes + if (matchPolicy == QPageSize::FuzzyOrientationMatch) { + // First try exact match in landscape layout + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + if (size.width() == qt_pageSizes[i].heightPoints && size.height() == qt_pageSizes[i].widthPoints) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + + // Then try fuzzy match in landscape layout + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + const int width = qt_pageSizes[i].heightPoints; + const int height = qt_pageSizes[i].widthPoints; + if (width >= minWidth && width <= maxWidth && height >= minHeight && height <= maxHeight) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + } + } + + if (match) + *match = size; + // Otherwise no match so Custom + return QPageSize::Custom; +} + +// Find matching standard page size for point size +static QPageSize::PageSizeId qt_idForSize(const QSizeF &size, QPageSize::Unit units, + QPageSize::SizeMatchPolicy matchPolicy, QSize *match) +{ + if (!size.isValid()) + return QPageSize::Custom; + + // Try exact match if units are the same + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + if (units == QPageSize::Millimeter) { + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + if (size.width() == qt_pageSizes[i].widthMillimeters && size.height() == qt_pageSizes[i].heightMillimeters) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + } else if (units == QPageSize::Inch) { + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + if (size.width() == qt_pageSizes[i].widthInches && size.height() == qt_pageSizes[i].heightInches) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + } else if (units == QPageSize::Point) { + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + if (size.width() == qt_pageSizes[i].widthPoints && size.height() == qt_pageSizes[i].heightPoints) { + if (match) + *match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints); + return qt_pageSizes[i].id; + } + } + } + + // If no exact match then convert to points and try match those + QSize points = qt_convertUnitsToPoints(size, units); + return qt_idForPointSize(points, matchPolicy, match); +} + +class QPageSizePrivate : public QSharedData +{ +public: + QPageSizePrivate(); + explicit QPageSizePrivate(QPageSize::PageSizeId pageSizeId); + QPageSizePrivate(const QSize &pointSize, + const QString &name, + QPageSize::SizeMatchPolicy matchPolicy); + QPageSizePrivate(const QSizeF &size, QPageSize::Unit units, + const QString &name, + QPageSize::SizeMatchPolicy matchPolicy); + QPageSizePrivate(const QString &key, const QSize &size, const QString &name); + QPageSizePrivate(int windowsId, const QSize &pointSize, const QString &name); + ~QPageSizePrivate(); + + bool operator==(const QPageSizePrivate &other) const; + bool isEquivalentTo(const QPageSizePrivate &other) const; + + bool isValid() const; + + QSizeF size(QPageSize::Unit units) const; + QSize sizePixels(int resolution) const; + +private: + friend class QPageSize; + + void init(QPageSize::PageSizeId id, const QString &name); + void init(const QSize &size, const QString &name); + void init(const QSizeF &size, QPageSize::Unit units, const QString &name); + + QString m_key; + QPageSize::PageSizeId m_id; + QSize m_pointSize; + QString m_name; + int m_windowsId; + QSizeF m_size; + QPageSize::Unit m_units; +}; + +QPageSizePrivate::QPageSizePrivate() + : m_id(QPageSize::Custom), + m_windowsId(0), + m_units(QPageSize::Point) +{ +} + +QPageSizePrivate::QPageSizePrivate(QPageSize::PageSizeId pageSizeId) + : m_id(QPageSize::Custom), + m_windowsId(0), + m_units(QPageSize::Point) +{ + if (pageSizeId >= QPageSize::PageSizeId(0) && pageSizeId <= QPageSize::LastPageSize) + init(pageSizeId, QString()); +} + +QPageSizePrivate::QPageSizePrivate(const QSize &pointSize, const QString &name, QPageSize::SizeMatchPolicy matchPolicy) + : m_id(QPageSize::Custom), + m_windowsId(0), + m_units(QPageSize::Point) +{ + if (pointSize.isValid()) { + QPageSize::PageSizeId id = qt_idForPointSize(pointSize, matchPolicy, 0); + id == QPageSize::Custom ? init(pointSize, name) : init(id, name); + } +} + +QPageSizePrivate::QPageSizePrivate(const QSizeF &size, QPageSize::Unit units, + const QString &name, QPageSize::SizeMatchPolicy matchPolicy) + : m_id(QPageSize::Custom), + m_windowsId(0), + m_units(QPageSize::Point) +{ + if (size.isValid()) { + QPageSize::PageSizeId id = qt_idForSize(size, units, matchPolicy, 0); + id == QPageSize::Custom ? init(size, units, name) : init(id, name); + } +} + +QPageSizePrivate::QPageSizePrivate(const QString &key, const QSize &pointSize, const QString &name) + : m_id(QPageSize::Custom), + m_windowsId(0), + m_units(QPageSize::Point) +{ + if (!key.isEmpty() && pointSize.isValid()) { + QPageSize::PageSizeId id = qt_idForPpdKey(key, 0); + // If not a known PPD key, check if size is a standard PPD size + if (id == QPageSize::Custom) + id = qt_idForPointSize(pointSize, QPageSize::FuzzyMatch, 0); + id == QPageSize::Custom ? init(pointSize, name) : init(id, name); + m_key = key; + } +} + +QPageSizePrivate::QPageSizePrivate(int windowsId, const QSize &pointSize, const QString &name) + : m_id(QPageSize::Custom), + m_windowsId(0), + m_units(QPageSize::Point) +{ + if (windowsId > 0 && pointSize.isValid()) { + QPageSize::PageSizeId id = qt_idForWindowsID(windowsId, 0); + // If not a known Windows ID, check if size is a standard PPD size + if (id == QPageSize::Custom) + id = qt_idForPointSize(pointSize, QPageSize::FuzzyMatch, 0); + id == QPageSize::Custom ? init(pointSize, name) : init(id, name); + m_windowsId = windowsId; + } +} + +QPageSizePrivate::~QPageSizePrivate() +{ +} + +// Init a standard PageSizeId +void QPageSizePrivate::init(QPageSize::PageSizeId id, const QString &name) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + m_id = id; + m_size = qt_definitionSize(id); + m_units = qt_pageSizes[id].definitionUnits; + m_key = qt_keyForPageSizeId(id); + m_name = name.isEmpty() ? QPageSize::name(id) : name; + m_windowsId = qt_pageSizes[id].windowsId; + m_pointSize = QSize(qt_pageSizes[id].widthPoints, qt_pageSizes[id].heightPoints); +} + +// Init a point size +void QPageSizePrivate::init(const QSize &size, const QString &name) +{ + m_id = QPageSize::Custom; + m_size = size; + m_units = QPageSize::Point; + m_key = qt_keyForCustomSize(m_size, m_units); + m_name = name.isEmpty() ? qt_nameForCustomSize(m_size, m_units) : name; + m_windowsId = 0; + m_pointSize = size; +} + +// Init a unit size +void QPageSizePrivate::init(const QSizeF &size, QPageSize::Unit units, const QString &name) +{ + m_id = QPageSize::Custom; + m_size = size; + m_units = units; + m_key = qt_keyForCustomSize(m_size, m_units); + if (name.isEmpty()) + m_name = qt_nameForCustomSize(m_size, m_units); + else + m_name = name; + m_windowsId = 0; + m_pointSize = qt_convertUnitsToPoints(m_size, m_units); +} + +bool QPageSizePrivate::operator==(const QPageSizePrivate &other) const +{ + return m_size == other.m_size + && m_units == other.m_units + && m_key == other.m_key + && m_name == other.m_name; +} + +bool QPageSizePrivate::isEquivalentTo(const QPageSizePrivate &other) const +{ + return m_pointSize == other.m_pointSize; +} + +bool QPageSizePrivate::isValid() const +{ + return m_pointSize.isValid() && !m_key.isEmpty() && !m_name.isEmpty(); +} + +QSizeF QPageSizePrivate::size(QPageSize::Unit units) const +{ + // If want units we've stored in, we already have them + if (units == m_units) + return m_size; + + // If want points we already have them + if (units == QPageSize::Point) + return QSizeF(m_pointSize.width(), m_pointSize.height()); + + // If a custom size do a conversion + if (m_id == QPageSize::Custom) + return qt_convertUnits(m_size, m_units, units); + + // Otherwise use the standard sizes + return qt_unitSize(m_id, units); +} + +QSize QPageSizePrivate::sizePixels(int resolution) const +{ + return qt_convertPointsToPixels(m_pointSize, resolution);; +} + + +/*! + \class QPageSize + \inmodule QtGui + \since 5.3 + \brief The QPageSize class describes the size and name of a defined page size + + This class implements support for the set of standard page sizes as defined + in the Adobe Postscript PPD Standard v4.3. It defines the standard set of + page sizes in points, millimeters and inches and ensures these sizes are + consistently used. Other size units can be used but will be calculated + results and so may not always be consistent. The defined point sizes are + always a integer, all other sizes can be fractions of a unit. + + The defined size is always in width x height order with no implied page + orientation. Note that it is possible for page sizes to be defined where the + width is greater than the height, such as QPageSize::Ledger, so you cannot + rely on comparing the width and height values to determine page orientation. + + For example, A4 is defined by the standard as 210mm x 297mm, 8.27in x 11.69in, + or 595pt x 842pt. + + You can also define custom page sizes with custom names in any units you want + and this unit size will be preserved and used as the base for all other unit + size calculations. + + When creating a QPageSize using a custom QSize you can choose if you want + QPageSize to try match the size to a standard page size. By default + QPaperSize uses a FuzzyMatch mode where it will match a given page size to + a standard page size if it falls within 3 postscript points of a defined + standard size. You can override this to request only an exact match but this + is not recommended as conversions between units can easily lose 3 points and + result in incorrect page sizes. + + A QPageSize instance may also be obtained by querying the supported page sizes + for a print device. In this case the localized name returned is that defined + by the printer itself. Note that the print device may not support the current + default locale language. + + The class also provides convenience methods for converting page size IDs to and from + various unit sizes. + + \sa QPagedPaintDevice, QPdfWriter +*/ + +/*! + \enum QPageSize::PageSizeId + + This enum type lists the available page sizes as defined in the Postscript + PPD standard. These values are duplicated in QPagedPaintDevice and QPrinter. + + The defined sizes are: + + \value A0 841 x 1189 mm + \value A1 594 x 841 mm + \value A2 420 x 594 mm + \value A3 297 x 420 mm + \value A4 210 x 297 mm, 8.26 x 11.69 inches + \value A5 148 x 210 mm + \value A6 105 x 148 mm + \value A7 74 x 105 mm + \value A8 52 x 74 mm + \value A9 37 x 52 mm + \value B0 1000 x 1414 mm + \value B1 707 x 1000 mm + \value B2 500 x 707 mm + \value B3 353 x 500 mm + \value B4 250 x 353 mm + \value B5 176 x 250 mm, 6.93 x 9.84 inches + \value B6 125 x 176 mm + \value B7 88 x 125 mm + \value B8 62 x 88 mm + \value B9 44 x 62 mm + \value B10 31 x 44 mm + \value C5E 163 x 229 mm + \value Comm10E 105 x 241 mm, U.S. Common 10 Envelope + \value DLE 110 x 220 mm + \value Executive 7.5 x 10 inches, 190.5 x 254 mm + \value Folio 210 x 330 mm + \value Ledger 431.8 x 279.4 mm + \value Legal 8.5 x 14 inches, 215.9 x 355.6 mm + \value Letter 8.5 x 11 inches, 215.9 x 279.4 mm + \value Tabloid 279.4 x 431.8 mm + \value Custom Unknown, or a user defined size. + \value A10 + \value A3Extra + \value A4Extra + \value A4Plus + \value A4Small + \value A5Extra + \value B5Extra + \value JisB0 + \value JisB1 + \value JisB2 + \value JisB3 + \value JisB4 + \value JisB5 + \value JisB6, + \value JisB7 + \value JisB8 + \value JisB9 + \value JisB10 + \value AnsiA = Letter + \value AnsiB = Ledger + \value AnsiC + \value AnsiD + \value AnsiE + \value LegalExtra + \value LetterExtra + \value LetterPlus + \value LetterSmall + \value TabloidExtra + \value ArchA + \value ArchB + \value ArchC + \value ArchD + \value ArchE + \value Imperial7x9 + \value Imperial8x10 + \value Imperial9x11 + \value Imperial9x12 + \value Imperial10x11 + \value Imperial10x13 + \value Imperial10x14 + \value Imperial12x11 + \value Imperial15x11 + \value ExecutiveStandard + \value Note + \value Quarto + \value Statement + \value SuperA + \value SuperB + \value Postcard + \value DoublePostcard + \value Prc16K + \value Prc32K + \value Prc32KBig + \value FanFoldUS + \value FanFoldGerman + \value FanFoldGermanLegal + \value EnvelopeB4 + \value EnvelopeB5 + \value EnvelopeB6 + \value EnvelopeC0 + \value EnvelopeC1 + \value EnvelopeC2 + \value EnvelopeC3 + \value EnvelopeC4 + \value EnvelopeC5 = C5E + \value EnvelopeC6 + \value EnvelopeC65 + \value EnvelopeC7 + \value EnvelopeDL = DLE + \value Envelope9 + \value Envelope10 = Comm10E + \value Envelope11 + \value Envelope12 + \value Envelope14 + \value EnvelopeMonarch + \value EnvelopePersonal + \value EnvelopeChou3 + \value EnvelopeChou4 + \value EnvelopeInvite + \value EnvelopeItalian + \value EnvelopeKaku2 + \value EnvelopeKaku3 + \value EnvelopePrc1 + \value EnvelopePrc2 + \value EnvelopePrc3 + \value EnvelopePrc4 + \value EnvelopePrc5 + \value EnvelopePrc6 + \value EnvelopePrc7 + \value EnvelopePrc8 + \value EnvelopePrc9 + \value EnvelopePrc10 + \value EnvelopeYou4 + \value LastPageSize = EnvelopeYou4 + \omitvalue NPageSize + \omitvalue NPaperSize + + Due to historic reasons QPageSize::Executive is not the same as the standard + Postscript and Windows Executive size, use QPageSize::ExecutiveStandard instead. + + The Postscript standard size QPageSize::Folio is different to the Windows + DMPAPER_FOLIO size, use the Postscript standard size QPageSize::FanFoldGermanLegal + if needed. +*/ + +/*! + \enum QPageSize::Unit + + This enum type is used to specify the measurement unit for page sizes. + + \value Millimeter + \value Point 1/72th of an inch + \value Inch + \value Pica 1/72th of a foot, 1/6th of an inch, 12 Points + \value Didot 1/72th of a French inch, 0.375 mm + \value Cicero 1/6th of a French inch, 12 Didot, 4.5mm +*/ + +/*! + \enum QPageSize::SizeMatchPolicy + + \value FuzzyMatch Match to a standard page size if within the margin of tolerance. + \value FuzzyOrientationMatch Match to a standard page size if within the margin of tolerance regardless of orientation. + \value ExactMatch Only match to a standard page size if the sizes match exactly. +*/ + +/*! + Creates a null QPageSize. +*/ + +QPageSize::QPageSize() + : d(new QPageSizePrivate()) +{ +} + +/*! + Creates a QPageSize of the standard \a pageSize. + + If \a pageSize is QPageSize::Custom then the resulting QPageSize will not + be valid. Use the custom size constructor instead. +*/ + +QPageSize::QPageSize(QPageSize::PageSizeId pageSize) + : d(new QPageSizePrivate(pageSize)) +{ +} + +/*! + Creates a QPageSize of the given \a pointSize in Points using the matching \a matchPolicy. + + If the given \a pointSize matches a standard QPageSize::PageSizeId, then that page + size will be used. Note that if the \a matchPolicy is FuzzyMatch this may result + in the \a pointSize being adjusted to the standard size. To prevent this happening + use a \a matchPolicy of ExactMatch instead. + + If the given \a pointSize is not a standard QPageSize::PageSizeId then a QPageSize::Custom + size will be created. + + If \a name is null then the standard localized name will be used. If a custom page + size then a custom name in the format "Custom (width x height)" will be created. + + The \a matchPolicy defaults to FuzzyMatch. +*/ + +QPageSize::QPageSize(const QSize &pointSize, const QString &name, SizeMatchPolicy matchPolicy) + : d(new QPageSizePrivate(pointSize, name, matchPolicy)) +{ +} + +/*! + Creates a custom page of the given \a size in \a units. + + If the given \a size matches a standard QPageSize::PageSizeId, then that page + size will be used. Note that if the \a matchPolicy is FuzzyMatch this may result + in the \a size being adjusted to the standard size. To prevent this happening + use a \a matchPolicy of ExactMatch instead. + + If the given \a size is not a standard QPageSize::PageSizeId then a QPageSize::Custom + size will be created. The original unit size will be preserved and used as the + base for all other unit size calculations. + + If \a name is null then a custom name will be created in the form + "Custom (width x height)" where the size is expressed in units provided. +*/ + +QPageSize::QPageSize(const QSizeF &size, QPageSize::Unit units, + const QString &name, SizeMatchPolicy matchPolicy) + : d(new QPageSizePrivate(size, units, name, matchPolicy)) +{ +} + +/*! + \internal + + Create page with given key, size and name, for use by printer plugin. +*/ + +QPageSize::QPageSize(const QString &key, const QSize &pointSize, const QString &name) + : d(new QPageSizePrivate(key, pointSize, name)) +{ +} + +/*! + \internal + + Create page with given windows ID, size and name, for use by printer plugin. +*/ + +QPageSize::QPageSize(int windowsId, const QSize &pointSize, const QString &name) + : d(new QPageSizePrivate(windowsId, pointSize, name)) +{ +} + +/*! + \internal + + Create page with given private backend +*/ + +QPageSize::QPageSize(QPageSizePrivate &dd) + : d(&dd) +{ +} + +/*! + Copy constructor, copies \a other to this. +*/ + +QPageSize::QPageSize(const QPageSize &other) + : d(other.d) +{ +} + +/*! + Destroys the page. +*/ + +QPageSize::~QPageSize() +{ +} + +/*! + Assignment operator, assigns \a other to this. +*/ + +QPageSize &QPageSize::operator=(const QPageSize &other) +{ + d = other.d; + return *this; +} + +/*! + \fn void QPageSize::swap(QPageSize &other) + + Swaps this QPageSize with \a other. This function is very fast and + never fails. +*/ + +/*! + \fn QPageSize &QPageSize::operator=(QPageSize &&other) + + Move-assigns \a other to this QPageSize instance, transferring the + ownership of the managed pointer to this instance. +*/ + +/*! + Returns \c true if this page is equal to the \a other page, i.e. if the + page has the same attributes. Current attributes are size and name. +*/ + +bool QPageSize::operator==(const QPageSize &other) const +{ + if (d == other.d) + return true; + return d && other.d && *d == *other.d; +} + +/*! + Returns \c true if this page is equivalent to the \a other page, i.e. if the + page has the same size regardless of other attributes like name. +*/ + +bool QPageSize::isEquivalentTo(const QPageSize &other) const +{ + if (d == other.d) + return true; + return d && other.d && d->isEquivalentTo(*other.d); +} + +/*! + Returns \c true if this page size is valid. + + The page size may be invalid if created with an invalid PageSizeId, or a + negative or invalid QSize or QSizeF, or the null constructor. +*/ + +bool QPageSize::isValid() const +{ + return d && d->isValid(); +} + +/*! + Returns the unique key of the page size. + + By default this is the PPD standard mediaOption keyword for the page size, + or the PPD custom format key. If the QPageSize instance was obtained from + a print device then this will be the key provided by the print device and + may differ from the standard key. + + If the QPageSize is invalid then the key will be an empty string. + + This key should never be shown to end users, it is an internal key only. + For a human-readable name use name(). + + \sa name() +*/ + +QString QPageSize::key() const +{ + return isValid() ? d->m_key : QString(); +} + +/*! + Returns a localized human-readable name for the page size. + + If the QPageSize instance was obtained from a print device then the name + used is that provided by the print device. Note that a print device may + not support the current default locale language. + + If the QPageSize is invalid then the name will be an empty string. +*/ + +QString QPageSize::name() const +{ + return isValid() ? d->m_name : QString(); +} + +/*! + Returns the standard QPageSize::PageSizeId of the page, or QPageSize::Custom. + + If the QPageSize is invalid then the ID will be QPageSize::Custom. +*/ + +QPageSize::PageSizeId QPageSize::id() const +{ + return isValid() ? d->m_id : QPageSize::Custom; +} + +/*! + Returns the Windows DMPAPER enum value for the page size. + + Not all valid PPD page sizes have a Windows equivalent, in which case 0 + will be returned. + + If the QPageSize is invalid then the Windows ID will be 0. + + \sa id() +*/ + +int QPageSize::windowsId() const +{ + if (!isValid()) + return 0; + return d->m_windowsId > 0 ? d->m_windowsId : QPageSize::windowsId(d->m_id); +} + +/*! + Returns the definition size of the page size. + + For a standard page size this will be the size as defined in the relevant + standard, i.e. ISO A4 will be defined in millimeters while ANSI Letter will + be defined in inches. + + For a custom page size this will be the original size used to create the + page size object. + + If the QPageSize is invalid then the QSizeF will be invalid. + + \sa definitionUnits() +*/ + +QSizeF QPageSize::definitionSize() const +{ + return isValid() ? d->m_size : QSizeF(); +} + +/*! + Returns the definition units of the page size. + + For a standard page size this will be the units as defined in the relevant + standard, i.e. ISO A4 will be defined in millimeters while ANSI Letter will + be defined in inches. + + For a custom page size this will be the original units used to create the + page size object. + + If the QPageSize is invalid then the QPageSize::Unit will be invalid. + + \sa definitionSize() +*/ + +QPageSize::Unit QPageSize::definitionUnits() const +{ + return isValid() ? d->m_units : QPageSize::Unit(-1); +} + +/*! + Returns the size of the page in the required \a units. + + If the QPageSize is invalid then the QSizeF will be invalid. +*/ + +QSizeF QPageSize::size(QPageSize::Unit units) const +{ + return isValid() ? d->size(units) : QSize(); +} + +/*! + Returns the size of the page in Postscript Points (1/72 of an inch). + + If the QPageSize is invalid then the QSize will be invalid. +*/ + +QSize QPageSize::sizePoints() const +{ + return isValid() ? d->m_pointSize : QSize(); +} + +/*! + Returns the size of the page in Device Pixels at the given \a resolution. + + If the QPageSize is invalid then the QSize will be invalid. +*/ + +QSize QPageSize::sizePixels(int resolution) const +{ + return isValid() ? d->sizePixels(resolution) : QSize(); +} + +/*! + Returns the page rectangle in the required \a units. + + If the QPageSize is invalid then the QRect will be invalid. +*/ + +QRectF QPageSize::rect(QPageSize::Unit units) const +{ + return isValid() ? QRectF(QPointF(0, 0), d->size(units)) : QRectF(); +} + +/*! + Returns the page rectangle in Postscript Points (1/72 of an inch). + + If the QPageSize is invalid then the QRect will be invalid. +*/ + +QRect QPageSize::rectPoints() const +{ + return isValid() ? QRect(QPoint(0, 0), d->m_pointSize) : QRect(); +} + +/*! + Returns the page rectangle in Device Pixels at the given \a resolution. + + If the QPageSize is invalid then the QRect will be invalid. +*/ + +QRect QPageSize::rectPixels(int resolution) const +{ + return isValid() ? QRect(QPoint(0, 0), d->sizePixels(resolution)) : QRect(); +} + +// Statics + +/*! + Returns the PPD mediaOption keyword of the standard \a pageSizeId. + + If the QPageSize is invalid then the key will be empty. +*/ + +QString QPageSize::key(QPageSize::PageSizeId pageSizeId) +{ + if (pageSizeId < QPageSize::PageSizeId(0) || pageSizeId > QPageSize::LastPageSize) + return QString(); + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + return QString::fromUtf8(qt_pageSizes[pageSizeId].mediaOption); +} + +/*! + Returns the localized name of the standard \a pageSizeId. + + If the QPageSize is invalid then the name will be empty. +*/ + +QString QPageSize::name(QPageSize::PageSizeId pageSizeId) +{ + if (pageSizeId < QPageSize::PageSizeId(0) || pageSizeId > QPageSize::LastPageSize) + return QString(); + + switch (pageSizeId) { + case QPageSize::A0: + return QCoreApplication::translate("QPageSize", "A0"); + case QPageSize::A1: + return QCoreApplication::translate("QPageSize", "A1"); + case QPageSize::A2: + return QCoreApplication::translate("QPageSize", "A2"); + case QPageSize::A3: + return QCoreApplication::translate("QPageSize", "A3"); + case QPageSize::A4: + return QCoreApplication::translate("QPageSize", "A4"); + case QPageSize::A5: + return QCoreApplication::translate("QPageSize", "A5"); + case QPageSize::A6: + return QCoreApplication::translate("QPageSize", "A6"); + case QPageSize::A7: + return QCoreApplication::translate("QPageSize", "A7"); + case QPageSize::A8: + return QCoreApplication::translate("QPageSize", "A8"); + case QPageSize::A9: + return QCoreApplication::translate("QPageSize", "A9"); + case QPageSize::A10: + return QCoreApplication::translate("QPageSize", "A10"); + case QPageSize::B0: + return QCoreApplication::translate("QPageSize", "B0"); + case QPageSize::B1: + return QCoreApplication::translate("QPageSize", "B1"); + case QPageSize::B2: + return QCoreApplication::translate("QPageSize", "B2"); + case QPageSize::B3: + return QCoreApplication::translate("QPageSize", "B3"); + case QPageSize::B4: + return QCoreApplication::translate("QPageSize", "B4"); + case QPageSize::B5: + return QCoreApplication::translate("QPageSize", "B5"); + case QPageSize::B6: + return QCoreApplication::translate("QPageSize", "B6"); + case QPageSize::B7: + return QCoreApplication::translate("QPageSize", "B7"); + case QPageSize::B8: + return QCoreApplication::translate("QPageSize", "B8"); + case QPageSize::B9: + return QCoreApplication::translate("QPageSize", "B9"); + case QPageSize::B10: + return QCoreApplication::translate("QPageSize", "B10"); + case QPageSize::Executive: + return QCoreApplication::translate("QPageSize", "Executive (7.5 x 10 in)"); + case QPageSize::ExecutiveStandard: + return QCoreApplication::translate("QPageSize", "Executive (7.25 x 10.5 in)"); + case QPageSize::Folio: + return QCoreApplication::translate("QPageSize", "Folio (8.27 x 13 in)"); + case QPageSize::Legal: + return QCoreApplication::translate("QPageSize", "Legal"); + case QPageSize::Letter: + return QCoreApplication::translate("QPageSize", "Letter / ANSI A"); + case QPageSize::Tabloid: + return QCoreApplication::translate("QPageSize", "Tabloid / ANSI B"); + case QPageSize::Ledger: + return QCoreApplication::translate("QPageSize", "Ledger / ANSI B"); + case QPageSize::Custom: + return QCoreApplication::translate("QPageSize", "Custom"); + case QPageSize::A3Extra: + return QCoreApplication::translate("QPageSize", "A3 Extra"); + case QPageSize::A4Extra: + return QCoreApplication::translate("QPageSize", "A4 Extra"); + case QPageSize::A4Plus: + return QCoreApplication::translate("QPageSize", "A4 Plus"); + case QPageSize::A4Small: + return QCoreApplication::translate("QPageSize", "A4 Small"); + case QPageSize::A5Extra: + return QCoreApplication::translate("QPageSize", "A5 Extra"); + case QPageSize::B5Extra: + return QCoreApplication::translate("QPageSize", "B5 Extra"); + case QPageSize::JisB0: + return QCoreApplication::translate("QPageSize", "JIS B0"); + case QPageSize::JisB1: + return QCoreApplication::translate("QPageSize", "JIS B1"); + case QPageSize::JisB2: + return QCoreApplication::translate("QPageSize", "JIS B2"); + case QPageSize::JisB3: + return QCoreApplication::translate("QPageSize", "JIS B3"); + case QPageSize::JisB4: + return QCoreApplication::translate("QPageSize", "JIS B4"); + case QPageSize::JisB5: + return QCoreApplication::translate("QPageSize", "JIS B5"); + case QPageSize::JisB6: + return QCoreApplication::translate("QPageSize", "JIS B6"); + case QPageSize::JisB7: + return QCoreApplication::translate("QPageSize", "JIS B7"); + case QPageSize::JisB8: + return QCoreApplication::translate("QPageSize", "JIS B8"); + case QPageSize::JisB9: + return QCoreApplication::translate("QPageSize", "JIS B9"); + case QPageSize::JisB10: + return QCoreApplication::translate("QPageSize", "JIS B10"); + case QPageSize::AnsiC: + return QCoreApplication::translate("QPageSize", "ANSI C"); + case QPageSize::AnsiD: + return QCoreApplication::translate("QPageSize", "ANSI D"); + case QPageSize::AnsiE: + return QCoreApplication::translate("QPageSize", "ANSI E"); + case QPageSize::LegalExtra: + return QCoreApplication::translate("QPageSize", "Legal Extra"); + case QPageSize::LetterExtra: + return QCoreApplication::translate("QPageSize", "Letter Extra"); + case QPageSize::LetterPlus: + return QCoreApplication::translate("QPageSize", "Letter Plus"); + case QPageSize::LetterSmall: + return QCoreApplication::translate("QPageSize", "Letter Small"); + case QPageSize::TabloidExtra: + return QCoreApplication::translate("QPageSize", "Tabliod Extra"); + case QPageSize::ArchA: + return QCoreApplication::translate("QPageSize", "Architect A"); + case QPageSize::ArchB: + return QCoreApplication::translate("QPageSize", "Architect B"); + case QPageSize::ArchC: + return QCoreApplication::translate("QPageSize", "Architect C"); + case QPageSize::ArchD: + return QCoreApplication::translate("QPageSize", "Architect D"); + case QPageSize::ArchE: + return QCoreApplication::translate("QPageSize", "Architect E"); + case QPageSize::Imperial7x9: + return QCoreApplication::translate("QPageSize", "7 x 9 in"); + case QPageSize::Imperial8x10: + return QCoreApplication::translate("QPageSize", "8 x 10 in"); + case QPageSize::Imperial9x11: + return QCoreApplication::translate("QPageSize", "9 x 11 in"); + case QPageSize::Imperial9x12: + return QCoreApplication::translate("QPageSize", "9 x 12 in"); + case QPageSize::Imperial10x11: + return QCoreApplication::translate("QPageSize", "10 x 11 in"); + case QPageSize::Imperial10x13: + return QCoreApplication::translate("QPageSize", "10 x 13 in"); + case QPageSize::Imperial10x14: + return QCoreApplication::translate("QPageSize", "10 x 14 in"); + case QPageSize::Imperial12x11: + return QCoreApplication::translate("QPageSize", "12 x 11 in"); + case QPageSize::Imperial15x11: + return QCoreApplication::translate("QPageSize", "15 x 11 in"); + case QPageSize::Note: + return QCoreApplication::translate("QPageSize", "Note"); + case QPageSize::Quarto: + return QCoreApplication::translate("QPageSize", "Quarto"); + case QPageSize::Statement: + return QCoreApplication::translate("QPageSize", "Statement"); + case QPageSize::SuperA: + return QCoreApplication::translate("QPageSize", "Super A"); + case QPageSize::SuperB: + return QCoreApplication::translate("QPageSize", "Super B"); + case QPageSize::Postcard: + return QCoreApplication::translate("QPageSize", "Postcard"); + case QPageSize::DoublePostcard: + return QCoreApplication::translate("QPageSize", "Double Postcard"); + case QPageSize::Prc16K: + return QCoreApplication::translate("QPageSize", "PRC 16K"); + case QPageSize::Prc32K: + return QCoreApplication::translate("QPageSize", "PRC 32K"); + case QPageSize::Prc32KBig: + return QCoreApplication::translate("QPageSize", "PRC 32K Big"); + case QPageSize::FanFoldUS: + return QCoreApplication::translate("QPageSize", "Fan-fold US (14.875 x 11 in)"); + case QPageSize::FanFoldGerman: + return QCoreApplication::translate("QPageSize", "Fan-fold German (8.5 x 12 in)"); + case QPageSize::FanFoldGermanLegal: + return QCoreApplication::translate("QPageSize", "Fan-fold German Legal (8.5 x 13 in)"); + case QPageSize::EnvelopeB4: + return QCoreApplication::translate("QPageSize", "Envelope B4"); + case QPageSize::EnvelopeB5: + return QCoreApplication::translate("QPageSize", "Envelope B5"); + case QPageSize::EnvelopeB6: + return QCoreApplication::translate("QPageSize", "Envelope B6"); + case QPageSize::EnvelopeC0: + return QCoreApplication::translate("QPageSize", "Envelope C0"); + case QPageSize::EnvelopeC1: + return QCoreApplication::translate("QPageSize", "Envelope C1"); + case QPageSize::EnvelopeC2: + return QCoreApplication::translate("QPageSize", "Envelope C2"); + case QPageSize::EnvelopeC3: + return QCoreApplication::translate("QPageSize", "Envelope C3"); + case QPageSize::EnvelopeC4: + return QCoreApplication::translate("QPageSize", "Envelope C4"); + case QPageSize::EnvelopeC5: // C5E + return QCoreApplication::translate("QPageSize", "Envelope C5"); + case QPageSize::EnvelopeC6: + return QCoreApplication::translate("QPageSize", "Envelope C6"); + case QPageSize::EnvelopeC65: + return QCoreApplication::translate("QPageSize", "Envelope C65"); + case QPageSize::EnvelopeC7: + return QCoreApplication::translate("QPageSize", "Envelope C7"); + case QPageSize::EnvelopeDL: // DLE: + return QCoreApplication::translate("QPageSize", "Envelope DL"); + case QPageSize::Envelope9: + return QCoreApplication::translate("QPageSize", "Envelope US 9"); + case QPageSize::Envelope10: // Comm10E + return QCoreApplication::translate("QPageSize", "Envelope US 10"); + case QPageSize::Envelope11: + return QCoreApplication::translate("QPageSize", "Envelope US 11"); + case QPageSize::Envelope12: + return QCoreApplication::translate("QPageSize", "Envelope US 12"); + case QPageSize::Envelope14: + return QCoreApplication::translate("QPageSize", "Envelope US 14"); + case QPageSize::EnvelopeMonarch: + return QCoreApplication::translate("QPageSize", "Envelope Monarch"); + case QPageSize::EnvelopePersonal: + return QCoreApplication::translate("QPageSize", "Envelope Personal"); + case QPageSize::EnvelopeChou3: + return QCoreApplication::translate("QPageSize", "Envelope Chou 3"); + case QPageSize::EnvelopeChou4: + return QCoreApplication::translate("QPageSize", "Envelope Chou 4"); + case QPageSize::EnvelopeInvite: + return QCoreApplication::translate("QPageSize", "Envelope Invite"); + case QPageSize::EnvelopeItalian: + return QCoreApplication::translate("QPageSize", "Envelope Italian"); + case QPageSize::EnvelopeKaku2: + return QCoreApplication::translate("QPageSize", "Envelope Kaku 2"); + case QPageSize::EnvelopeKaku3: + return QCoreApplication::translate("QPageSize", "Envelope Kaku 3"); + case QPageSize::EnvelopePrc1: + return QCoreApplication::translate("QPageSize", "Envelope PRC 1"); + case QPageSize::EnvelopePrc2: + return QCoreApplication::translate("QPageSize", "Envelope PRC 2"); + case QPageSize::EnvelopePrc3: + return QCoreApplication::translate("QPageSize", "Envelope PRC 3"); + case QPageSize::EnvelopePrc4: + return QCoreApplication::translate("QPageSize", "Envelope PRC 4"); + case QPageSize::EnvelopePrc5: + return QCoreApplication::translate("QPageSize", "Envelope PRC 5"); + case QPageSize::EnvelopePrc6: + return QCoreApplication::translate("QPageSize", "Envelope PRC 6"); + case QPageSize::EnvelopePrc7: + return QCoreApplication::translate("QPageSize", "Envelope PRC 7"); + case QPageSize::EnvelopePrc8: + return QCoreApplication::translate("QPageSize", "Envelope PRC 8"); + case QPageSize::EnvelopePrc9: + return QCoreApplication::translate("QPageSize", "Envelope PRC 9"); + case QPageSize::EnvelopePrc10: + return QCoreApplication::translate("QPageSize", "Envelope PRC 10"); + case QPageSize::EnvelopeYou4: + return QCoreApplication::translate("QPageSize", "Envelope You 4"); + } + return QString(); +} + +/*! + Returns the standard QPageSize::PageSizeId of the given \a pointSize in + points using the given \a matchPolicy. + + If using FuzzyMatch then the point size of the PageSizeId returned may not + exactly match the \a pointSize you passed in. You should call + QPageSize::sizePoints() using the returned PageSizeId to find out the actual + point size of the PageSizeId before using it in any calculations. +*/ + +QPageSize::PageSizeId QPageSize::id(const QSize &pointSize, QPageSize::SizeMatchPolicy matchPolicy) +{ + return qt_idForPointSize(pointSize, matchPolicy, 0); +} + +/*! + Returns the standard QPageSize::PageSizeId of the given \a size in \a units + using the given \a matchPolicy. + + If using FuzzyMatch then the unit size of the PageSizeId returned may not + exactly match the \a size you passed in. You should call + QPageSize::size() using the returned PageSizeId to find out the actual + unit size of the PageSizeId before using it in any calculations. +*/ + +QPageSize::PageSizeId QPageSize::id(const QSizeF &size, QPageSize::Unit units, + QPageSize::SizeMatchPolicy matchPolicy) +{ + return qt_idForSize(size, units, matchPolicy, 0); +} + +/*! + Returns the PageSizeId for the given Windows DMPAPER enum value \a windowsId. + + If there is no matching PageSizeId then QPageSize::Custom is returned. +*/ + +QPageSize::PageSizeId QPageSize::id(int windowsId) +{ + return qt_idForWindowsID(windowsId); +} + +/*! + Returns the Windows DMPAPER enum value of the standard \a pageSizeId. + + Not all valid PPD page sizes have a Windows equivalent, in which case 0 + will be returned. +*/ + +int QPageSize::windowsId(QPageSize::PageSizeId pageSizeId) +{ + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + return qt_pageSizes[pageSizeId].windowsId; +} + +/*! + Returns the definition size of the standard \a pageSizeId. + + To obtain the definition units, call QPageSize::definitionUnits(). +*/ + +QSizeF QPageSize::definitionSize(QPageSize::PageSizeId pageSizeId) +{ + if (pageSizeId == QPageSize::Custom) + return QSizeF(); + return qt_definitionSize(pageSizeId); +} + +/*! + Returns the definition units of the standard \a pageSizeId. + + To obtain the definition size, call QPageSize::definitionSize(). +*/ + +QPageSize::Unit QPageSize::definitionUnits(QPageSize::PageSizeId pageSizeId) +{ + if (pageSizeId == QPageSize::Custom) + return QPageSize::Unit(-1); + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + return qt_pageSizes[pageSizeId].definitionUnits; +} + +/*! + Returns the size of the standard \a pageSizeId in the requested \a units. +*/ + +QSizeF QPageSize::size(QPageSize::PageSizeId pageSizeId, QPageSize::Unit units) +{ + if (pageSizeId == QPageSize::Custom) + return QSizeF(); + return qt_unitSize(pageSizeId, units); +} + +/*! + Returns the size of the standard \a pageSizeId in Points. +*/ + +QSize QPageSize::sizePoints(QPageSize::PageSizeId pageSizeId) +{ + if (pageSizeId == QPageSize::Custom) + return QSize(); + Q_ASSERT(pageSizesCount == QPageSize::LastPageSize + 1); + return QSize(qt_pageSizes[pageSizeId].widthPoints, qt_pageSizes[pageSizeId].heightPoints); +} + +/*! + Returns the size of the standard \a pageSizeId in Device Pixels + for the given \a resolution. +*/ + +QSize QPageSize::sizePixels(QPageSize::PageSizeId pageSizeId, int resolution) +{ + if (pageSizeId == QPageSize::Custom) + return QSize(); + return qt_convertPointsToPixels(QPageSize::sizePoints(pageSizeId), resolution); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QPageSize &pageSize) +{ + if (pageSize.isValid()) { + QString output = QStringLiteral("QPageSize(\"%1\", \"%2\", %3x%4pt, %5)"); + output = output.arg(pageSize.name()) + .arg(pageSize.key()) + .arg(pageSize.sizePoints().width()) + .arg(pageSize.sizePoints().height()) + .arg(pageSize.id()); + dbg.nospace() << output; + } else { + dbg.nospace() << QStringLiteral("QPageSize()"); + } + return dbg.space(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h new file mode 100644 index 0000000000..af9181355b --- /dev/null +++ b/src/gui/painting/qpagesize.h @@ -0,0 +1,310 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPAGESIZE_H +#define QPAGESIZE_H + +#include + +QT_BEGIN_NAMESPACE + +#if defined(B0) +#undef B0 // Terminal hang-up. We assume that you do not want that. +#endif + +class QPageSizePrivate; +class QString; +class QSize; +class QSizeF; + +class Q_GUI_EXPORT QPageSize +{ +public: + + // ### Qt6 Re-order and remove duplicates + // NOTE: Must keep in sync with QPagedPrintEngine and QPrinter + enum PageSizeId { + // Existing Qt sizes + A4, + B5, + Letter, + Legal, + Executive, + A0, + A1, + A2, + A3, + A5, + A6, + A7, + A8, + A9, + B0, + B1, + B10, + B2, + B3, + B4, + B6, + B7, + B8, + B9, + C5E, + Comm10E, + DLE, + Folio, + Ledger, + Tabloid, + Custom, + + // New values derived from PPD standard + A10, + A3Extra, + A4Extra, + A4Plus, + A4Small, + A5Extra, + B5Extra, + + JisB0, + JisB1, + JisB2, + JisB3, + JisB4, + JisB5, + JisB6, + JisB7, + JisB8, + JisB9, + JisB10, + + // AnsiA = Letter, + // AnsiB = Ledger, + AnsiC, + AnsiD, + AnsiE, + LegalExtra, + LetterExtra, + LetterPlus, + LetterSmall, + TabloidExtra, + + ArchA, + ArchB, + ArchC, + ArchD, + ArchE, + + Imperial7x9, + Imperial8x10, + Imperial9x11, + Imperial9x12, + Imperial10x11, + Imperial10x13, + Imperial10x14, + Imperial12x11, + Imperial15x11, + + ExecutiveStandard, + Note, + Quarto, + Statement, + SuperA, + SuperB, + Postcard, + DoublePostcard, + Prc16K, + Prc32K, + Prc32KBig, + + FanFoldUS, + FanFoldGerman, + FanFoldGermanLegal, + + EnvelopeB4, + EnvelopeB5, + EnvelopeB6, + EnvelopeC0, + EnvelopeC1, + EnvelopeC2, + EnvelopeC3, + EnvelopeC4, + // EnvelopeC5 = C5E, + EnvelopeC6, + EnvelopeC65, + EnvelopeC7, + // EnvelopeDL = DLE, + + Envelope9, + // Envelope10 = Comm10E, + Envelope11, + Envelope12, + Envelope14, + EnvelopeMonarch, + EnvelopePersonal, + + EnvelopeChou3, + EnvelopeChou4, + EnvelopeInvite, + EnvelopeItalian, + EnvelopeKaku2, + EnvelopeKaku3, + EnvelopePrc1, + EnvelopePrc2, + EnvelopePrc3, + EnvelopePrc4, + EnvelopePrc5, + EnvelopePrc6, + EnvelopePrc7, + EnvelopePrc8, + EnvelopePrc9, + EnvelopePrc10, + EnvelopeYou4, + + // Last item, with commonly used synynoms from QPagedPrintEngine / QPrinter + LastPageSize = EnvelopeYou4, + NPageSize = LastPageSize, + NPaperSize = LastPageSize, + + // Convenience overloads for naming consistency + AnsiA = Letter, + AnsiB = Ledger, + EnvelopeC5 = C5E, + EnvelopeDL = DLE, + Envelope10 = Comm10E + }; + + // NOTE: Must keep in sync with QPageLayout::Unit and QPrinter::Unit + enum Unit { + Millimeter, + Point, + Inch, + Pica, + Didot, + Cicero + }; + + enum SizeMatchPolicy { + FuzzyMatch, + FuzzyOrientationMatch, + ExactMatch + }; + + QPageSize(); + explicit QPageSize(QPageSize::PageSizeId pageSizeId); + QPageSize(const QSize &pointSize, + const QString &name = QString(), + QPageSize::SizeMatchPolicy matchPolicy = QPageSize::FuzzyMatch); + QPageSize(const QSizeF &size, QPageSize::Unit units, + const QString &name = QString(), + QPageSize::SizeMatchPolicy matchPolicy = QPageSize::FuzzyMatch); + QPageSize(const QPageSize &other); + ~QPageSize(); + + QPageSize &operator=(const QPageSize &other); +#ifdef Q_COMPILER_RVALUE_REFS + QPageSize &operator=(QPageSize &&other) { swap(other); return *this; } +#endif + + void swap(QPageSize &other) { d.swap(other.d); } + + bool operator==(const QPageSize &other) const; + bool isEquivalentTo(const QPageSize &other) const; + + bool isValid() const; + + QString key() const; + QString name() const; + + QPageSize::PageSizeId id() const; + + int windowsId() const; + + QSizeF definitionSize() const; + QPageSize::Unit definitionUnits() const; + + QSizeF size(QPageSize::Unit units) const; + QSize sizePoints() const; + QSize sizePixels(int resolution) const; + + QRectF rect(QPageSize::Unit units) const; + QRect rectPoints() const; + QRect rectPixels(int resolution) const; + + static QString key(QPageSize::PageSizeId pageSizeId); + static QString name(QPageSize::PageSizeId pageSizeId); + + static QPageSize::PageSizeId id(const QSize &pointSize, + QPageSize::SizeMatchPolicy matchPolicy = QPageSize::FuzzyMatch); + static QPageSize::PageSizeId id(const QSizeF &size, QPageSize::Unit units, + QPageSize::SizeMatchPolicy matchPolicy = QPageSize::FuzzyMatch); + + static QPageSize::PageSizeId id(int windowsId); + static int windowsId(QPageSize::PageSizeId pageSizeId); + + static QSizeF definitionSize(QPageSize::PageSizeId pageSizeId); + static QPageSize::Unit definitionUnits(QPageSize::PageSizeId pageSizeId); + + static QSizeF size(QPageSize::PageSizeId pageSizeId, QPageSize::Unit units); + static QSize sizePoints(QPageSize::PageSizeId pageSizeId); + static QSize sizePixels(QPageSize::PageSizeId pageSizeId, int resolution); + +private: + friend class QPageSizePrivate; + QPageSize(const QString &key, const QSize &pointSize, const QString &name); + QPageSize(int windowsId, const QSize &pointSize, const QString &name); + QPageSize(QPageSizePrivate &dd); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QPageSize) + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QPageSize &pageSize); +#endif + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPageSize) +Q_DECLARE_METATYPE(QPageSize::PageSizeId) +Q_DECLARE_METATYPE(QPageSize::Unit) + +#endif // QPAGESIZE_H diff --git a/src/printsupport/kernel/qprinter.h b/src/printsupport/kernel/qprinter.h index 679f3af043..17afdc2157 100644 --- a/src/printsupport/kernel/qprinter.h +++ b/src/printsupport/kernel/qprinter.h @@ -75,6 +75,7 @@ public: enum Orientation { Portrait, Landscape }; + // ### Qt6 Remove in favor of QPage::PageSize #ifndef Q_QDOC typedef PageSize PaperSize; #else -- cgit v1.2.3 From 5eeed00f4d01d5033594854399a33d6ec54c3e58 Mon Sep 17 00:00:00 2001 From: John Layt Date: Fri, 27 Dec 2013 17:55:48 +0100 Subject: QPageLayout - Add new QPageLayout class New QPageLayout to encapsulate page layout details including page size, orientation and margins. Scale may be added later. Subsequent changes will use this class in the paged paint devices, paint engines, print engines, and print plugins to replace multiple inconsistent local implementations. [ChangeLog][QtGui] Added class QPageLayout to support handling page layouts including the page size, orientation and margins. Change-Id: Ife1ddd6c2a8d1516542be2eb37425111f41cd5c7 Reviewed-by: Lars Knoll Reviewed-by: Andy Shaw --- src/gui/painting/painting.pri | 2 + src/gui/painting/qpagelayout.cpp | 971 +++++++++++++++++++++++++++++++++++++++ src/gui/painting/qpagelayout.h | 155 +++++++ 3 files changed, 1128 insertions(+) create mode 100644 src/gui/painting/qpagelayout.cpp create mode 100644 src/gui/painting/qpagelayout.h (limited to 'src') diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 8a51c3f379..ed45b8ea17 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -19,6 +19,7 @@ HEADERS += \ painting/qoutlinemapper_p.h \ painting/qpagedpaintdevice.h \ painting/qpagedpaintdevice_p.h \ + painting/qpagelayout.h \ painting/qpagesize.h \ painting/qpaintdevice.h \ painting/qpaintengine.h \ @@ -67,6 +68,7 @@ SOURCES += \ painting/qmemrotate.cpp \ painting/qoutlinemapper.cpp \ painting/qpagedpaintdevice.cpp \ + painting/qpagelayout.cpp \ painting/qpagesize.cpp \ painting/qpaintdevice.cpp \ painting/qpaintengine.cpp \ diff --git a/src/gui/painting/qpagelayout.cpp b/src/gui/painting/qpagelayout.cpp new file mode 100644 index 0000000000..7ae117e423 --- /dev/null +++ b/src/gui/painting/qpagelayout.cpp @@ -0,0 +1,971 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qpagelayout.h" + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +static qreal qt_clamp(qreal value, qreal min, qreal max) +{ + return qMin(qMax(value, min), max); +} + +// Multiplier for converting units to points. +Q_GUI_EXPORT qreal qt_pointMultiplier(QPageLayout::Unit unit) +{ + switch (unit) { + case QPageLayout::Millimeter: + return 2.83464566929; + case QPageLayout::Point: + return 1.0; + case QPageLayout::Inch: + return 72.0; + case QPageLayout::Pica: + return 12; + case QPageLayout::Didot: + return 1.065826771; + case QPageLayout::Cicero: + return 12.789921252; + } + return 1.0; +} + +// Multiplier for converting pixels to points. +extern qreal qt_pixelMultiplier(int resolution); + +QPointF qt_convertPoint(const QPointF &xy, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits) +{ + // If the size have the same units, or are all 0, then don't need to convert + if (fromUnits == toUnits || xy.isNull()) + return xy; + + // If converting to points then convert and round to 0 decimal places + if (toUnits == QPageLayout::Point) { + const qreal multiplier = qt_pointMultiplier(fromUnits); + return QPointF(qRound(xy.x() * multiplier), + qRound(xy.y() * multiplier)); + } + + // If converting to other units, need to convert to unrounded points first + QPointF pointXy = (fromUnits == QPageLayout::Point) ? xy : xy * qt_pointMultiplier(fromUnits); + + // Then convert from points to required units rounded to 2 decimal places + const qreal multiplier = qt_pointMultiplier(toUnits); + return QPointF(qRound(pointXy.x() * 100 / multiplier) / 100.0, + qRound(pointXy.y() * 100 / multiplier) / 100.0); +} + +Q_GUI_EXPORT QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits) +{ + // If the margins have the same units, or are all 0, then don't need to convert + if (fromUnits == toUnits || margins.isNull()) + return margins; + + // If converting to points then convert and round to 0 decimal places + if (toUnits == QPageLayout::Point) { + const qreal multiplier = qt_pointMultiplier(fromUnits); + return QMarginsF(qRound(margins.left() * multiplier), + qRound(margins.top() * multiplier), + qRound(margins.right() * multiplier), + qRound(margins.bottom() * multiplier)); + } + + // If converting to other units, need to convert to unrounded points first + QMarginsF pointMargins = fromUnits == QPageLayout::Point ? margins : margins * qt_pointMultiplier(fromUnits); + + // Then convert from points to required units rounded to 2 decimal places + const qreal multiplier = qt_pointMultiplier(toUnits); + return QMarginsF(qRound(pointMargins.left() * 100 / multiplier) / 100.0, + qRound(pointMargins.top() * 100 / multiplier) / 100.0, + qRound(pointMargins.right() * 100 / multiplier) / 100.0, + qRound(pointMargins.bottom() * 100 / multiplier) / 100.0); +} + +class QPageLayoutPrivate : public QSharedData +{ +public: + + QPageLayoutPrivate(); + QPageLayoutPrivate(const QPageSize &pageSize, QPageLayout::Orientation orientation, + const QMarginsF &margins, QPageLayout::Unit units, + const QMarginsF &minMargins); + ~QPageLayoutPrivate(); + + bool operator==(const QPageLayoutPrivate &other) const; + bool isEquivalentTo(const QPageLayoutPrivate &other) const; + + bool isValid() const; + + void clampMargins(const QMarginsF &margins); + + QMarginsF margins(QPageLayout::Unit units) const; + QMargins marginsPoints() const; + QMargins marginsPixels(int resolution) const; + + void setDefaultMargins(const QMarginsF &minMargins); + + QSizeF paintSize() const; + + QRectF fullRect() const; + QRectF fullRect(QPageLayout::Unit units) const; + QRect fullRectPoints() const; + QRect fullRectPixels(int resolution) const; + + QRectF paintRect() const; + +private: + friend class QPageLayout; + + QSizeF fullSizeUnits(QPageLayout::Unit units) const; + + QPageSize m_pageSize; + QPageLayout::Orientation m_orientation; + QPageLayout::Mode m_mode; + QPageLayout::Unit m_units; + QSizeF m_fullSize; + QMarginsF m_margins; + QMarginsF m_minMargins; + QMarginsF m_maxMargins; +}; + +QPageLayoutPrivate::QPageLayoutPrivate() + : m_orientation(QPageLayout::Landscape), + m_mode(QPageLayout::StandardMode) +{ +} + +QPageLayoutPrivate::QPageLayoutPrivate(const QPageSize &pageSize, QPageLayout::Orientation orientation, + const QMarginsF &margins, QPageLayout::Unit units, + const QMarginsF &minMargins) + : m_pageSize(pageSize), + m_orientation(orientation), + m_mode(QPageLayout::StandardMode), + m_units(units), + m_margins(margins) +{ + m_fullSize = fullSizeUnits(m_units); + setDefaultMargins(minMargins); +} + +QPageLayoutPrivate::~QPageLayoutPrivate() +{ +} + +bool QPageLayoutPrivate::operator==(const QPageLayoutPrivate &other) const +{ + return m_pageSize == other.m_pageSize + && m_orientation == other.m_orientation + && m_units == other.m_units + && m_margins == other.m_margins + && m_minMargins == other.m_minMargins + && m_maxMargins == other.m_maxMargins; +} + +bool QPageLayoutPrivate::isEquivalentTo(const QPageLayoutPrivate &other) const +{ + return m_pageSize.isEquivalentTo(other.m_pageSize) + && m_orientation == other.m_orientation + && qt_convertMargins(m_margins, m_units, QPageLayout::Point) + == qt_convertMargins(other.m_margins, other.m_units, QPageLayout::Point); +} + +bool QPageLayoutPrivate::isValid() const +{ + return m_pageSize.isValid(); +} + +void QPageLayoutPrivate::clampMargins(const QMarginsF &margins) +{ + m_margins = QMarginsF(qt_clamp(margins.left(), m_minMargins.left(), m_maxMargins.left()), + qt_clamp(margins.top(), m_minMargins.top(), m_maxMargins.top()), + qt_clamp(margins.right(), m_minMargins.right(), m_maxMargins.right()), + qt_clamp(margins.bottom(), m_minMargins.bottom(), m_maxMargins.bottom())); +} + +QMarginsF QPageLayoutPrivate::margins(QPageLayout::Unit units) const +{ + return qt_convertMargins(m_margins, m_units, units); +} + +QMargins QPageLayoutPrivate::marginsPoints() const +{ + return qt_convertMargins(m_margins, m_units, QPageLayout::Point).toMargins(); +} + +QMargins QPageLayoutPrivate::marginsPixels(int resolution) const +{ + return marginsPoints() / qt_pixelMultiplier(resolution); +} + +void QPageLayoutPrivate::setDefaultMargins(const QMarginsF &minMargins) +{ + m_minMargins = minMargins; + m_maxMargins = QMarginsF(m_fullSize.width() - m_minMargins.right(), + m_fullSize.height() - m_minMargins.bottom(), + m_fullSize.width() - m_minMargins.left(), + m_fullSize.height() - m_minMargins.top()); + if (m_mode == QPageLayout::StandardMode) + clampMargins(m_margins); +} + +QSizeF QPageLayoutPrivate::fullSizeUnits(QPageLayout::Unit units) const +{ + QSizeF fullPageSize = m_pageSize.size(QPageSize::Unit(units)); + return m_orientation == QPageLayout::Landscape ? fullPageSize.transposed() : fullPageSize; +} + +QRectF QPageLayoutPrivate::fullRect() const +{ + return QRectF(QPointF(0, 0), m_fullSize); +} + +QRectF QPageLayoutPrivate::fullRect(QPageLayout::Unit units) const +{ + return units == m_units ? fullRect() : QRectF(QPointF(0, 0), fullSizeUnits(units)); +} + +QRect QPageLayoutPrivate::fullRectPoints() const +{ + if (m_orientation == QPageLayout::Landscape) + return QRect(QPoint(0, 0), m_pageSize.sizePoints().transposed()); + else + return QRect(QPoint(0, 0), m_pageSize.sizePoints()); +} + +QRect QPageLayoutPrivate::fullRectPixels(int resolution) const +{ + if (m_orientation == QPageLayout::Landscape) + return QRect(QPoint(0, 0), m_pageSize.sizePixels(resolution).transposed()); + else + return QRect(QPoint(0, 0), m_pageSize.sizePixels(resolution)); +} + +QRectF QPageLayoutPrivate::paintRect() const +{ + return m_mode == QPageLayout::FullPageMode ? fullRect() : fullRect() - m_margins; +} + + +/*! + \class QPageLayout + \inmodule QtGui + \since 5.3 + \brief Describes the size, orientation and margins of a page. + + The QPageLayout class defines the layout of a page in a paged document, with the + page size, orientation and margins able to be set and the full page and paintable + page rectangles defined by those attributes able to be queried in a variety of units. + + The page size is defined by the QPageSize class which can be queried for page size + attributes. Note that the QPageSize itself is always defined in a Portrait + orientation. + + The minimum margins can be defined for the layout but normally default to 0. + When used in conjunction with Qt's printing support the minimum margins + will reflect the minimum printable area defined by the printer. + + In the default StandardMode the current margins and minimum margins are + always taken into account. The paintable rectangle is the full page + rectangle less the current margins, and the current margins can only be set + to values between the minimum margins and the maximum margins allowed by + the full page size. + + In FullPageMode the current margins and minimum margins are not taken + into account. The paintable rectangle is the full page rectangle, and the + current margins can be set to any values regardless of the minimum margins + and page size. + + \sa QPageSize +*/ + +/*! + \enum QPageLayout::Unit + + This enum type is used to specify the measurement unit for page layout and margins. + + \value Millimeter + \value Point 1/72th of an inch + \value Inch + \value Pica 1/72th of a foot, 1/6th of an inch, 12 Points + \value Didot 1/72th of a French inch, 0.375 mm + \value Cicero 1/6th of a French inch, 12 Didot, 4.5mm +*/ + +/*! + \enum QPageLayout::Orientation + + This enum type defines the page orientation + + \value Portrait The page size is used in its default orientation + \value Landscape The page size is rotated through 90 degrees + + Note that some standard page sizes are defined with a width larger than + their height, hence the orientation is defined relative to the standard + page size and not using the relative page dimensions. +*/ + +/*! + \enum QPageLayout::Mode + + Defines the page layout mode + + \value StandardMode Paint Rect includes margins, margins must fall between the minimum and maximum. + \value FullPageMode Paint Rect excludes margins, margins can be any value and must be managed manually. +*/ + +/*! + Creates an invalid QPageLayout. +*/ + +QPageLayout::QPageLayout() + : d(new QPageLayoutPrivate()) +{ +} + +/*! + Creates a QPageLayout with the given \a pageSize, \a orientation and + \a margins in the given \a units. + + Optionally define the minimum allowed margins \a minMargins, e.g. the minimum + margins able to be printed by a physical print device. + + The constructed QPageLayout will be in StandardMode. + + The \a margins given will be clamped to the minimum margins and the maximum + margins allowed by the page size. +*/ + +QPageLayout::QPageLayout(const QPageSize &pageSize, QPageLayout::Orientation orientation, + const QMarginsF &margins, QPageLayout::Unit units, + const QMarginsF &minMargins) + : d(new QPageLayoutPrivate(pageSize, orientation, margins, units, minMargins)) +{ +} + +/*! + Copy constructor, copies \a other to this. +*/ + +QPageLayout::QPageLayout(const QPageLayout &other) + : d(other.d) +{ +} + +/*! + Destroys the page layout. +*/ + +QPageLayout::~QPageLayout() +{ +} + +/*! + Assignment operator, assigns \a other to this. +*/ + +QPageLayout &QPageLayout::operator=(const QPageLayout &other) +{ + d = other.d; + return *this; +} + +/*! + \fn void QPageLayout::swap(QPageLayout &other) + + Swaps this page layout with \a other. This function is very fast and + never fails. +*/ + +/*! + \fn QPageLayout &QPageLayout::operator=(QPageLayout &&other) + + Move-assigns \a other to this QPageLayout instance, transferring the + ownership of the managed pointer to this instance. +*/ + +/*! + Returns \c true if this page layout is equal to the \a other page layout, + i.e. if all the attributes are exactly equal. + + Note that this is a strict equality, especially for page size where the + QPageSize ID, name and size must exactly match, and the margins where the + units must match. + + \sa isEquivalentTo() +*/ + +bool QPageLayout::operator==(const QPageLayout &other) const +{ + if (d && other.d) + return (*d == *other.d); + return (d == other.d); +} + +/*! + Returns \c true if this page layout is equivalent to the \a other page layout, + i.e. if the page has the same size, margins and orientation. +*/ + +bool QPageLayout::isEquivalentTo(const QPageLayout &other) const +{ + return d && other.d && d->isEquivalentTo(*other.d); +} + +/*! + Returns \c true if this page layout is valid. +*/ + +bool QPageLayout::isValid() const +{ + return d->isValid(); +} + +/*! + Sets a page layout mode to \a mode. +*/ + +void QPageLayout::setMode(QPageLayout::Mode mode) +{ + d->m_mode = mode; +} + +/*! + Returns the page layout mode. +*/ + +QPageLayout::Mode QPageLayout::mode() const +{ + return d->m_mode; +} + +/*! + Sets the page size of the page layout to \a pageSize. + + Optionally define the minimum allowed margins \a minMargins, e.g. the minimum + margins able to be printed by a physical print device, otherwise the + minimum margins will default to 0. + + If StandardMode is set then the existing margins will be clamped + to the new minimum margins and the maximum margins allowed by the page size. + If FullPageMode is set then the existing margins will be unchanged. +*/ + +void QPageLayout::setPageSize(const QPageSize &pageSize, const QMarginsF &minMargins) +{ + if (!pageSize.isValid()) + return; + d->m_pageSize = pageSize; + d->m_fullSize = d->fullSizeUnits(d->m_units); + d->setDefaultMargins(minMargins); +} + +/*! + Returns the page size of the page layout. + + Note that the QPageSize is always defined in a Portrait orientation. To + obtain a size that takes the set orientation into account you must use + fullRect(). +*/ + +QPageSize QPageLayout::pageSize() const +{ + return d->m_pageSize; +} + +/*! + Sets the page orientation of the page layout to \a orientation. + + Changing the orientation does not affect the current margins or + the minimum margins. +*/ + +void QPageLayout::setOrientation(QPageLayout::Orientation orientation) +{ + if (orientation != d->m_orientation) { + d->m_orientation = orientation; + d->m_fullSize = d->fullSizeUnits(d->m_units); + // Adust the max margins to reflect change in max page size + const qreal change = d->m_fullSize.width() - d->m_fullSize.height(); + d->m_maxMargins.setLeft(d->m_maxMargins.left() + change); + d->m_maxMargins.setRight(d->m_maxMargins.right() + change); + d->m_maxMargins.setTop(d->m_maxMargins.top() - change); + d->m_maxMargins.setBottom(d->m_maxMargins.bottom() - change); + } +} + +/*! + Returns the page orientation of the page layout. +*/ + +QPageLayout::Orientation QPageLayout::orientation() const +{ + return d->m_orientation; +} + +/*! + Sets the \a units used to define the page layout. +*/ + +void QPageLayout::setUnits(QPageLayout::Unit units) +{ + if (units != d->m_units) { + d->m_margins = qt_convertMargins(d->m_margins, d->m_units, units); + d->m_minMargins = qt_convertMargins(d->m_minMargins, d->m_units, units); + d->m_maxMargins = qt_convertMargins(d->m_maxMargins, d->m_units, units); + d->m_units = units; + d->m_fullSize = d->fullSizeUnits(d->m_units); + } +} + +/*! + Returns the units the page layout is currently defined in. +*/ + +QPageLayout::Unit QPageLayout::units() const +{ + return d->m_units; +} + +/*! + Sets the page margins of the page layout to \a margins + Returns true if the margins were successfully set. + + The units used are those currently defined for the layout. To use different + units then call setUnits() first. + + If in the default StandardMode then all the new margins must fall between the + minimum margins set and the maximum margins allowed by the page size, + otherwise the margins will not be set. + + If in FullPageMode then any margin values will be accepted. + + \sa margins(), units() +*/ + +bool QPageLayout::setMargins(const QMarginsF &margins) +{ + if (d->m_mode == QPageLayout::FullPageMode) { + d->m_margins = margins; + return true; + } else if (margins.left() >= d->m_minMargins.left() + && margins.right() >= d->m_minMargins.right() + && margins.top() >= d->m_minMargins.top() + && margins.bottom() >= d->m_minMargins.bottom() + && margins.left() <= d->m_maxMargins.left() + && margins.right() <= d->m_maxMargins.right() + && margins.top() <= d->m_maxMargins.top() + && margins.bottom() <= d->m_maxMargins.bottom()) { + d->m_margins = margins; + return true; + } + return false; +} + +/*! + Sets the left page margin of the page layout to \a leftMargin. + Returns true if the margin was successfully set. + + The units used are those currently defined for the layout. To use different + units call setUnits() first. + + If in the default StandardMode then the new margin must fall between the + minimum margin set and the maximum margin allowed by the page size, + otherwise the margin will not be set. + + If in FullPageMode then any margin values will be accepted. + + \sa setMargins(), margins() +*/ + +bool QPageLayout::setLeftMargin(qreal leftMargin) +{ + if (d->m_mode == QPageLayout::FullPageMode + || (leftMargin >= d->m_minMargins.left() && leftMargin <= d->m_maxMargins.left())) { + d->m_margins.setLeft(leftMargin); + return true; + } + return false; +} + +/*! + Sets the right page margin of the page layout to \a rightMargin. + Returns true if the margin was successfully set. + + The units used are those currently defined for the layout. To use different + units call setUnits() first. + + If in the default StandardMode then the new margin must fall between the + minimum margin set and the maximum margin allowed by the page size, + otherwise the margin will not be set. + + If in FullPageMode then any margin values will be accepted. + + \sa setMargins(), margins() +*/ + +bool QPageLayout::setRightMargin(qreal rightMargin) +{ + if (d->m_mode == QPageLayout::FullPageMode + || (rightMargin >= d->m_minMargins.right() && rightMargin <= d->m_maxMargins.right())) { + d->m_margins.setRight(rightMargin); + return true; + } + return false; +} + +/*! + Sets the top page margin of the page layout to \a topMargin. + Returns true if the margin was successfully set. + + The units used are those currently defined for the layout. To use different + units call setUnits() first. + + If in the default StandardMode then the new margin must fall between the + minimum margin set and the maximum margin allowed by the page size, + otherwise the margin will not be set. + + If in FullPageMode then any margin values will be accepted. + + \sa setMargins(), margins() +*/ + +bool QPageLayout::setTopMargin(qreal topMargin) +{ + if (d->m_mode == QPageLayout::FullPageMode + || (topMargin >= d->m_minMargins.top() && topMargin <= d->m_maxMargins.top())) { + d->m_margins.setTop(topMargin); + return true; + } + return false; +} + +/*! + Sets the bottom page margin of the page layout to \a bottomMargin. + Returns true if the margin was successfully set. + + The units used are those currently defined for the layout. To use different + units call setUnits() first. + + If in the default StandardMode then the new margin must fall between the + minimum margin set and the maximum margin allowed by the page size, + otherwise the margin will not be set. + + If in FullPageMode then any margin values will be accepted. + + \sa setMargins(), margins() +*/ + +bool QPageLayout::setBottomMargin(qreal bottomMargin) +{ + if (d->m_mode == QPageLayout::FullPageMode + || (bottomMargin >= d->m_minMargins.bottom() && bottomMargin <= d->m_maxMargins.bottom())) { + d->m_margins.setBottom(bottomMargin); + return true; + } + return false; +} + +/*! + Returns the margins of the page layout using the currently set units. + + \sa setMargins(), units() +*/ + +QMarginsF QPageLayout::margins() const +{ + return d->m_margins; +} + +/*! + Returns the margins of the page layout using the requested \a units. + + \sa setMargins(), margins() +*/ + +QMarginsF QPageLayout::margins(QPageLayout::Unit units) const +{ + return d->margins(units); +} + +/*! + Returns the margins of the page layout in Postscript Points (1/72 of an inch). + + \sa setMargins(), margins() +*/ + +QMargins QPageLayout::marginsPoints() const +{ + return d->marginsPoints(); +} + +/*! + Returns the margins of the page layout in device pixels for the given \a resolution. + + \sa setMargins() +*/ + +QMargins QPageLayout::marginsPixels(int resolution) const +{ + return d->marginsPixels(resolution); +} + +/*! + Sets the minimum page margins of the page layout to \a minMargins. + + It is not recommended to override the default values set for a page size + as this may be the minimum printable area for a physical print device. + + If the StandardMode mode is set then the existing margins will be clamped + to the new \a minMargins and the maximum allowed by the page size. If the + FullPageMode is set then the existing margins will be unchanged. + + \sa minimumMargins(), setMargins() +*/ + +void QPageLayout::setMinimumMargins(const QMarginsF &minMargins) +{ + d->setDefaultMargins(minMargins); +} + +/*! + Returns the minimum margins of the page layout. + + \sa setMinimumMargins(), maximumMargins() +*/ + +QMarginsF QPageLayout::minimumMargins() const +{ + return d->m_minMargins; +} + +/*! + Returns the maximum margins that would be applied if the page layout was + in StandardMode. + + The maximum margins allowed are calculated as the full size of the page + minus the minimum margins set. For example, if the page width is 100 points + and the minimum right margin is 10 points, then the maximum left margin + will be 90 points. + + \sa setMinimumMargins(), minimumMargins() +*/ + +QMarginsF QPageLayout::maximumMargins() const +{ + return d->m_maxMargins; +} + +/*! + Returns the full page rectangle in the current layout units. + + The page rectangle takes into account the page size and page orientation, + but not the page margins. + + \sa paintRect(), units() +*/ + +QRectF QPageLayout::fullRect() const +{ + return isValid() ? d->fullRect() : QRect(); +} + +/*! + Returns the full page rectangle in the required \a units. + + The page rectangle takes into account the page size and page orientation, + but not the page margins. + + \sa paintRect() +*/ + +QRectF QPageLayout::fullRect(QPageLayout::Unit units) const +{ + return isValid() ? d->fullRect(units) : QRect(); +} + +/*! + Returns the full page rectangle in Postscript Points (1/72 of an inch). + + The page rectangle takes into account the page size and page orientation, + but not the page margins. + + \sa paintRect() +*/ + +QRect QPageLayout::fullRectPoints() const +{ + return isValid() ? d->fullRectPoints() : QRect(); +} + +/*! + Returns the full page rectangle in device pixels for the given \a resolution. + + The page rectangle takes into account the page size and page orientation, + but not the page margins. + + \sa paintRect() +*/ + +QRect QPageLayout::fullRectPixels(int resolution) const +{ + return isValid() ? d->fullRectPixels(resolution) : QRect(); +} + +/*! + Returns the page rectangle in the current layout units. + + The paintable rectangle takes into account the page size, orientation + and margins. + + If the FullPageMode mode is set then the fullRect() is returned and + the margins must be manually managed. +*/ + +QRectF QPageLayout::paintRect() const +{ + return isValid() ? d->paintRect() : QRectF(); +} + +/*! + Returns the page rectangle in the required \a units. + + The paintable rectangle takes into account the page size, orientation + and margins. + + If the FullPageMode mode is set then the fullRect() is returned and + the margins must be manually managed. +*/ + +QRectF QPageLayout::paintRect(QPageLayout::Unit units) const +{ + if (!isValid()) + return QRectF(); + if (units == d->m_units) + return d->paintRect(); + return d->m_mode == QPageLayout::FullPageMode ? d->fullRect(units) + : d->fullRect(units) - d->margins(units); +} + +/*! + Returns the paintable rectangle in rounded Postscript Points (1/72 of an inch). + + The paintable rectangle takes into account the page size, orientation + and margins. + + If the FullPageMode mode is set then the fullRect() is returned and + the margins must be manually managed. +*/ + +QRect QPageLayout::paintRectPoints() const +{ + if (!isValid()) + return QRect(); + return d->m_mode == QPageLayout::FullPageMode ? d->fullRectPoints() + : d->fullRectPoints() - d->marginsPoints(); +} + +/*! + Returns the paintable rectangle in rounded device pixels for the given \a resolution. + + The paintable rectangle takes into account the page size, orientation + and margins. + + If the FullPageMode mode is set then the fullRect() is returned and + the margins must be manually managed. +*/ + +QRect QPageLayout::paintRectPixels(int resolution) const +{ + if (!isValid()) + return QRect(); + return d->m_mode == QPageLayout::FullPageMode ? d->fullRectPixels(resolution) + : d->fullRectPixels(resolution) - d->marginsPixels(resolution); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QPageLayout &layout) +{ + if (layout.isValid()) { + QString output = QStringLiteral("QPageLayout(%1, %2, l:%3 r:%4 t:%5 b:%6 %7)"); + QString units; + switch (layout.units()) { + case QPageLayout::Millimeter: + units = QStringLiteral("mm"); + break; + case QPageLayout::Point: + units = QStringLiteral("pt"); + break; + case QPageLayout::Inch: + units = QStringLiteral("in"); + break; + case QPageLayout::Pica: + units = QStringLiteral("pc"); + break; + case QPageLayout::Didot: + units = QStringLiteral("DD"); + break; + case QPageLayout::Cicero: + units = QStringLiteral("CC"); + break; + } + output = output.arg(layout.pageSize().name()) + .arg(layout.orientation() == QPageLayout::Portrait ? QStringLiteral("Portrait") : QStringLiteral("Landscape")) + .arg(layout.margins().left()) + .arg(layout.margins().right()) + .arg(layout.margins().top()) + .arg(layout.margins().bottom()) + .arg(units); + dbg.nospace() << output; + } else { + dbg.nospace() << QStringLiteral("QPageLayout()"); + } + return dbg.space(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h new file mode 100644 index 0000000000..86e430e311 --- /dev/null +++ b/src/gui/painting/qpagelayout.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPAGELAYOUT_H +#define QPAGELAYOUT_H + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QPageLayoutPrivate; +class QMarginsF; + +class Q_GUI_EXPORT QPageLayout +{ +public: + + // NOTE: Must keep in sync with QPageSize::Unit and QPrinter::Unit + enum Unit { + Millimeter, + Point, + Inch, + Pica, + Didot, + Cicero + }; + + // NOTE: Must keep in sync with QPrinter::Orientation + enum Orientation { + Portrait, + Landscape + }; + + enum Mode { + StandardMode, // Paint Rect includes margins + FullPageMode // Paint Rect excludes margins + }; + + QPageLayout(); + QPageLayout(const QPageSize &pageSize, QPageLayout::Orientation orientation, + const QMarginsF &margins, QPageLayout::Unit units = QPageLayout::Point, + const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0)); + QPageLayout(const QPageLayout &other); + ~QPageLayout(); + + QPageLayout &operator=(const QPageLayout &other); + #ifdef Q_COMPILER_RVALUE_REFS + QPageLayout &operator=(QPageLayout &&other) { swap(other); return *this; } +#endif + + void swap(QPageLayout &other) { d.swap(other.d); } + + bool operator==(const QPageLayout &other) const; + bool isEquivalentTo(const QPageLayout &other) const; + + bool isValid() const; + + void setMode(QPageLayout::Mode mode); + QPageLayout::Mode mode() const; + + void setPageSize(const QPageSize &pageSize, + const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0)); + QPageSize pageSize() const; + + void setOrientation(QPageLayout::Orientation orientation); + QPageLayout::Orientation orientation() const; + + void setUnits(QPageLayout::Unit units); + QPageLayout::Unit units() const; + + bool setMargins(const QMarginsF &margins); + bool setLeftMargin(qreal leftMargin); + bool setRightMargin(qreal rightMargin); + bool setTopMargin(qreal topMargin); + bool setBottomMargin(qreal bottomMargin); + + QMarginsF margins() const; + QMarginsF margins(QPageLayout::Unit units) const; + QMargins marginsPoints() const; + QMargins marginsPixels(int resolution) const; + + void setMinimumMargins(const QMarginsF &minMargins); + QMarginsF minimumMargins() const; + QMarginsF maximumMargins() const; + + QRectF fullRect() const; + QRectF fullRect(QPageLayout::Unit units) const; + QRect fullRectPoints() const; + QRect fullRectPixels(int resolution) const; + + QRectF paintRect() const; + QRectF paintRect(QPageLayout::Unit units) const; + QRect paintRectPoints() const; + QRect paintRectPixels(int resolution) const; + +private: + friend class QPageLayoutPrivate; + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QPageLayout) + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QPageLayout &pageLayout); +#endif + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPageLayout) +Q_DECLARE_METATYPE(QPageLayout::Unit) +Q_DECLARE_METATYPE(QPageLayout::Orientation) + +#endif // QPAGELAYOUT_H -- cgit v1.2.3 From f50d46e5eb257528828998a465634d9044cdd17f Mon Sep 17 00:00:00 2001 From: John Layt Date: Tue, 10 Dec 2013 18:42:44 +0100 Subject: QPlatformPrintDevice - New QPA base class Add a new QPA class to abstract Print Devices. Each platform instance will encapsulate all required details about a print device instead of the code being distributed throughout the print engine and print plugin. Change-Id: I7f6a537ad55a6e7f599d83f461b1e2ee62b15094 Reviewed-by: Lars Knoll --- src/gui/painting/qpagesize.h | 1 + src/printsupport/kernel/kernel.pri | 5 + src/printsupport/kernel/qplatformprintdevice.cpp | 389 +++++++++++++++++++++ src/printsupport/kernel/qplatformprintdevice.h | 180 ++++++++++ .../kernel/qplatformprintersupport.cpp | 28 ++ src/printsupport/kernel/qplatformprintersupport.h | 10 + src/printsupport/kernel/qprint_p.h | 304 ++++++++++++++++ src/printsupport/kernel/qprintdevice.cpp | 251 +++++++++++++ src/printsupport/kernel/qprintdevice_p.h | 145 ++++++++ 9 files changed, 1313 insertions(+) create mode 100644 src/printsupport/kernel/qplatformprintdevice.cpp create mode 100644 src/printsupport/kernel/qplatformprintdevice.h create mode 100644 src/printsupport/kernel/qprint_p.h create mode 100644 src/printsupport/kernel/qprintdevice.cpp create mode 100644 src/printsupport/kernel/qprintdevice_p.h (limited to 'src') diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h index af9181355b..c8a472747d 100644 --- a/src/gui/painting/qpagesize.h +++ b/src/gui/painting/qpagesize.h @@ -289,6 +289,7 @@ public: private: friend class QPageSizePrivate; + friend class QPlatformPrintDevice; QPageSize(const QString &key, const QSize &pointSize, const QString &name); QPageSize(int windowsId, const QSize &pointSize, const QString &name); QPageSize(QPageSizePrivate &dd); diff --git a/src/printsupport/kernel/kernel.pri b/src/printsupport/kernel/kernel.pri index 67fcc8597c..cbbb14342a 100644 --- a/src/printsupport/kernel/kernel.pri +++ b/src/printsupport/kernel/kernel.pri @@ -1,11 +1,14 @@ HEADERS += \ $$PWD/qpaintengine_alpha_p.h \ $$PWD/qpaintengine_preview_p.h \ + $$PWD/qprint_p.h \ + $$PWD/qprintdevice_p.h \ $$PWD/qprintengine.h \ $$PWD/qprinter.h \ $$PWD/qprinter_p.h \ $$PWD/qprinterinfo.h \ $$PWD/qprinterinfo_p.h \ + $$PWD/qplatformprintdevice.h \ $$PWD/qplatformprintplugin.h \ $$PWD/qplatformprintersupport.h \ $$PWD/qtprintsupportglobal.h @@ -13,9 +16,11 @@ HEADERS += \ SOURCES += \ $$PWD/qpaintengine_alpha.cpp \ $$PWD/qpaintengine_preview.cpp \ + $$PWD/qprintdevice.cpp \ $$PWD/qprintengine_pdf.cpp \ $$PWD/qprinter.cpp \ $$PWD/qprinterinfo.cpp \ + $$PWD/qplatformprintdevice.cpp \ $$PWD/qplatformprintplugin.cpp \ $$PWD/qplatformprintersupport.cpp diff --git a/src/printsupport/kernel/qplatformprintdevice.cpp b/src/printsupport/kernel/qplatformprintdevice.cpp new file mode 100644 index 0000000000..df0ef3111b --- /dev/null +++ b/src/printsupport/kernel/qplatformprintdevice.cpp @@ -0,0 +1,389 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPrintSupport 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformprintdevice.h" + +#include "qprintdevice_p.h" +#include "qprintdialog.h" + +#include + +QT_BEGIN_NAMESPACE + +QPlatformPrintDevice::QPlatformPrintDevice() + : m_isRemote(false), + m_supportsMultipleCopies(false), + m_supportsCollateCopies(false), + m_havePageSizes(false), + m_supportsCustomPageSizes(false), + m_haveResolutions(false), + m_haveInputSlots(false), + m_haveOutputBins(false), + m_haveDuplexModes(false), + m_haveColorModes(false) +{ +} + +QPlatformPrintDevice::QPlatformPrintDevice(const QString &id) + : m_id(id), + m_isRemote(false), + m_supportsMultipleCopies(false), + m_supportsCollateCopies(false), + m_havePageSizes(false), + m_supportsCustomPageSizes(false), + m_haveResolutions(false), + m_haveInputSlots(false), + m_haveOutputBins(false), + m_haveDuplexModes(false), + m_haveColorModes(false) +{ +} + +QPlatformPrintDevice::~QPlatformPrintDevice() +{ +} + +bool QPlatformPrintDevice::operator==(const QPlatformPrintDevice &other) const +{ + return m_id == other.m_id; +} + +QString QPlatformPrintDevice::id() const +{ + return m_id; +} + +QString QPlatformPrintDevice::name() const +{ + return m_name; +} + +QString QPlatformPrintDevice::location() const +{ + return m_location; +} + +QString QPlatformPrintDevice::makeAndModel() const +{ + return m_makeAndModel; +} + +bool QPlatformPrintDevice::isValid() const +{ + return false; +} + +bool QPlatformPrintDevice::isDefault() const +{ + return false; +} + +bool QPlatformPrintDevice::isRemote() const +{ + return m_isRemote; +} + +bool QPlatformPrintDevice::isValidPageLayout(const QPageLayout &layout, int resolution) const +{ + // Check the page size is supported + if (!supportedPageSize(layout.pageSize()).isValid()) + return false; + + // Check the margins are valid + QMarginsF pointMargins = layout.margins(QPageLayout::Point); + QMarginsF printMargins = printableMargins(layout.pageSize(), layout.orientation(), resolution); + return pointMargins.left() >= printMargins.left() + && pointMargins.right() >= printMargins.right() + && pointMargins.top() >= printMargins.top() + && pointMargins.bottom() >= printMargins.bottom(); +} + +QPrint::DeviceState QPlatformPrintDevice::state() const +{ + return QPrint::Error; +} + +bool QPlatformPrintDevice::supportsMultipleCopies() const +{ + return m_supportsMultipleCopies; +} + +bool QPlatformPrintDevice::supportsCollateCopies() const +{ + return m_supportsCollateCopies; +} + +void QPlatformPrintDevice::loadPageSizes() const +{ +} + +QPageSize QPlatformPrintDevice::defaultPageSize() const +{ + return QPageSize(); +} + +QList QPlatformPrintDevice::supportedPageSizes() const +{ + if (!m_havePageSizes) + loadPageSizes(); + return m_pageSizes.toList(); +} + +QPageSize QPlatformPrintDevice::supportedPageSize(const QPageSize &pageSize) const +{ + if (!pageSize.isValid()) + return QPageSize(); + + if (!m_havePageSizes) + loadPageSizes(); + + // First try match on name and id for case where printer defines same size twice with different names + // e.g. Windows defines DMPAPER_11X17 and DMPAPER_TABLOID with names "11x17" and "Tabloid", but both + // map to QPageSize::Tabloid / PPD Key "Tabloid" / ANSI B Tabloid + if (pageSize.id() != QPageSize::Custom) { + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.id() == pageSize.id() && ps.name() == pageSize.name()) + return ps; + } + } + + // Next try match on id only if not custom + if (pageSize.id() != QPageSize::Custom) { + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.id() == pageSize.id()) + return ps; + } + } + + // Next try a match on size, in case it's a custom with a different name + return supportedPageSizeMatch(pageSize); +} + +QPageSize QPlatformPrintDevice::supportedPageSize(QPageSize::PageSizeId pageSizeId) const +{ + if (!m_havePageSizes) + loadPageSizes(); + + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.id() == pageSizeId) + return ps; + } + + // If no supported page size found, try use a custom size instead if supported + return supportedPageSizeMatch(QPageSize(pageSizeId)); +} + +QPageSize QPlatformPrintDevice::supportedPageSize(const QString &pageName) const +{ + if (!m_havePageSizes) + loadPageSizes(); + + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.name() == pageName) + return ps; + } + + return QPageSize(); +} + +QPageSize QPlatformPrintDevice::supportedPageSize(const QSize &sizePoints) const +{ + if (!m_havePageSizes) + loadPageSizes(); + + // Try to find a supported page size based on fuzzy-matched point size + return supportedPageSizeMatch(QPageSize(sizePoints)); +} + +QPageSize QPlatformPrintDevice::supportedPageSize(const QSizeF &size, QPageSize::Unit units) const +{ + if (!m_havePageSizes) + loadPageSizes(); + + // Try to find a supported page size based on fuzzy-matched unit size + return supportedPageSizeMatch(QPageSize(size, units)); +} + +QPageSize QPlatformPrintDevice::supportedPageSizeMatch(const QPageSize &pageSize) const +{ + // Try to find a supported page size based on point size + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.sizePoints() == pageSize.sizePoints()) + return ps; + } + return QPageSize(); +} + +bool QPlatformPrintDevice::supportsCustomPageSizes() const +{ + return m_supportsCustomPageSizes; +} + +QSize QPlatformPrintDevice::minimumPhysicalPageSize() const +{ + return m_minimumPhysicalPageSize; +} + +QSize QPlatformPrintDevice::maximumPhysicalPageSize() const +{ + return m_maximumPhysicalPageSize; +} + +QMarginsF QPlatformPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + Q_UNUSED(pageSize) + Q_UNUSED(orientation) + Q_UNUSED(resolution) + return QMarginsF(0, 0, 0, 0); +} + +void QPlatformPrintDevice::loadResolutions() const +{ +} + +int QPlatformPrintDevice::defaultResolution() const +{ + return 0; +} + +QList QPlatformPrintDevice::supportedResolutions() const +{ + if (!m_haveResolutions) + loadResolutions(); + return m_resolutions.toList(); +} + +void QPlatformPrintDevice::loadInputSlots() const +{ +} + +QPrint::InputSlot QPlatformPrintDevice::defaultInputSlot() const +{ + QPrint::InputSlot input; + input.key = QByteArrayLiteral("Auto"); + input.name = QPrintDialog::tr("Automatic"); + input.id = QPrint::Auto; + return input; +} + +QList QPlatformPrintDevice::supportedInputSlots() const +{ + if (!m_haveInputSlots) + loadInputSlots(); + return m_inputSlots.toList(); +} + +void QPlatformPrintDevice::loadOutputBins() const +{ +} + +QPrint::OutputBin QPlatformPrintDevice::defaultOutputBin() const +{ + QPrint::OutputBin output; + output.key = QByteArrayLiteral("Auto"); + output.name = QPrintDialog::tr("Automatic"); + output.id = QPrint::AutoOutputBin; + return output; +} + +QList QPlatformPrintDevice::supportedOutputBins() const +{ + if (!m_haveOutputBins) + loadOutputBins(); + return m_outputBins.toList(); +} + +void QPlatformPrintDevice::loadDuplexModes() const +{ +} + +QPrint::DuplexMode QPlatformPrintDevice::defaultDuplexMode() const +{ + return QPrint::DuplexNone; +} + +QList QPlatformPrintDevice::supportedDuplexModes() const +{ + if (!m_haveDuplexModes) + loadDuplexModes(); + return m_duplexModes.toList(); +} + +void QPlatformPrintDevice::loadColorModes() const +{ +} + +QPrint::ColorMode QPlatformPrintDevice::defaultColorMode() const +{ + return QPrint::GrayScale; +} + +QList QPlatformPrintDevice::supportedColorModes() const +{ + if (!m_haveColorModes) + loadColorModes(); + return m_colorModes.toList(); +} + +void QPlatformPrintDevice::loadMimeTypes() const +{ +} + +QList QPlatformPrintDevice::supportedMimeTypes() const +{ + if (!m_haveMimeTypes) + loadMimeTypes(); + return m_mimeTypes.toList(); +} + +QPageSize QPlatformPrintDevice::createPageSize(const QString &key, const QSize &size, const QString &localizedName) +{ + return QPageSize(key, size, localizedName); +} + +QPageSize QPlatformPrintDevice::createPageSize(int windowsId, const QSize &size, const QString &localizedName) +{ + return QPageSize(windowsId, size, localizedName); +} + +QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qplatformprintdevice.h b/src/printsupport/kernel/qplatformprintdevice.h new file mode 100644 index 0000000000..04d614085f --- /dev/null +++ b/src/printsupport/kernel/qplatformprintdevice.h @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPrintSupport 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMPRINTDEVICE_H +#define QPLATFORMPRINTDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "qplatformprintdevice.h" + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_PRINTSUPPORT_EXPORT QPlatformPrintDevice : public QSharedData +{ +public: + QPlatformPrintDevice(); + explicit QPlatformPrintDevice(const QString &id); + virtual ~QPlatformPrintDevice(); + + QPlatformPrintDevice *clone(); + + bool operator==(const QPlatformPrintDevice &other) const; + + virtual QString id() const; + virtual QString name() const; + virtual QString location() const; + virtual QString makeAndModel() const; + + virtual bool isValid() const; + virtual bool isDefault() const; + virtual bool isRemote() const; + + virtual QPrint::DeviceState state() const; + + virtual bool isValidPageLayout(const QPageLayout &layout, int resolution) const; + + virtual bool supportsMultipleCopies() const; + virtual bool supportsCollateCopies() const; + + virtual QPageSize defaultPageSize() const; + virtual QList supportedPageSizes() const; + + virtual QPageSize supportedPageSize(const QPageSize &pageSize) const; + virtual QPageSize supportedPageSize(QPageSize::PageSizeId pageSizeId) const; + virtual QPageSize supportedPageSize(const QString &pageName) const; + virtual QPageSize supportedPageSize(const QSize &pointSize) const; + virtual QPageSize supportedPageSize(const QSizeF &size, QPageSize::Unit units) const; + + virtual bool supportsCustomPageSizes() const; + + virtual QSize minimumPhysicalPageSize() const; + virtual QSize maximumPhysicalPageSize() const; + + virtual QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, + int resolution) const; + + virtual int defaultResolution() const; + virtual QList supportedResolutions() const; + + virtual QPrint::InputSlot defaultInputSlot() const; + virtual QList supportedInputSlots() const; + + virtual QPrint::OutputBin defaultOutputBin() const; + virtual QList supportedOutputBins() const; + + virtual QPrint::DuplexMode defaultDuplexMode() const; + virtual QList supportedDuplexModes() const; + + virtual QPrint::ColorMode defaultColorMode() const; + virtual QList supportedColorModes() const; + + virtual QList supportedMimeTypes() const; + + static QPageSize createPageSize(const QString &key, const QSize &size, const QString &localizedName); + static QPageSize createPageSize(int windowsId, const QSize &size, const QString &localizedName); + +protected: + virtual void loadPageSizes() const; + virtual void loadResolutions() const; + virtual void loadInputSlots() const; + virtual void loadOutputBins() const; + virtual void loadDuplexModes() const; + virtual void loadColorModes() const; + virtual void loadMimeTypes() const; + + QPageSize supportedPageSizeMatch(const QPageSize &pageSize) const; + + QString m_id; + QString m_name; + QString m_location; + QString m_makeAndModel; + + bool m_isRemote; + + bool m_supportsMultipleCopies; + bool m_supportsCollateCopies; + + mutable bool m_havePageSizes; + mutable QVector m_pageSizes; + + bool m_supportsCustomPageSizes; + + QSize m_minimumPhysicalPageSize; + QSize m_maximumPhysicalPageSize; + + mutable bool m_haveResolutions; + mutable QVector m_resolutions; + + mutable bool m_haveInputSlots; + mutable QVector m_inputSlots; + + mutable bool m_haveOutputBins; + mutable QVector m_outputBins; + + mutable bool m_haveDuplexModes; + mutable QVector m_duplexModes; + + mutable bool m_haveColorModes; + mutable QVector m_colorModes; + + mutable bool m_haveMimeTypes; + mutable QVector m_mimeTypes; +}; + +QT_END_NAMESPACE + +#endif // QPLATFORMPRINTDEVICE_H diff --git a/src/printsupport/kernel/qplatformprintersupport.cpp b/src/printsupport/kernel/qplatformprintersupport.cpp index 4d80e55ab6..cddf979928 100644 --- a/src/printsupport/kernel/qplatformprintersupport.cpp +++ b/src/printsupport/kernel/qplatformprintersupport.cpp @@ -40,10 +40,12 @@ ****************************************************************************/ #include "qplatformprintersupport.h" +#include "qplatformprintdevice.h" #include #include +#include #ifndef QT_NO_PRINTER @@ -77,6 +79,32 @@ QPaintEngine *QPlatformPrinterSupport::createPaintEngine(QPrintEngine *, QPrinte return 0; } +QPrintDevice QPlatformPrinterSupport::createPrintDevice(QPlatformPrintDevice *device) +{ + return QPrintDevice(device); +} + +QPrintDevice QPlatformPrinterSupport::createPrintDevice(const QString &id) +{ + Q_UNUSED(id) + return QPrintDevice(); +} + +QPrintDevice QPlatformPrinterSupport::createDefaultPrintDevice() +{ + return createPrintDevice(defaultPrintDeviceId()); +} + +QStringList QPlatformPrinterSupport::availablePrintDeviceIds() const +{ + return QStringList(); +} + +QString QPlatformPrinterSupport::defaultPrintDeviceId() const +{ + return QString(); +} + QList QPlatformPrinterSupport::supportedPaperSizes(const QPrinterInfo &) const { return QList(); diff --git a/src/printsupport/kernel/qplatformprintersupport.h b/src/printsupport/kernel/qplatformprintersupport.h index c4ffcffd1e..6a4ecc09c8 100644 --- a/src/printsupport/kernel/qplatformprintersupport.h +++ b/src/printsupport/kernel/qplatformprintersupport.h @@ -52,6 +52,7 @@ #include +#include #include #include @@ -61,6 +62,8 @@ QT_BEGIN_NAMESPACE typedef QHash PrinterOptions; +class QPlatformPrintDevice; +class QPrintDevice; class QPrintEngine; class Q_PRINTSUPPORT_EXPORT QPlatformPrinterSupport @@ -71,6 +74,12 @@ public: virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); virtual QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode); + + virtual QPrintDevice createPrintDevice(const QString &id); + virtual QPrintDevice createDefaultPrintDevice(); + virtual QStringList availablePrintDeviceIds() const; + virtual QString defaultPrintDeviceId() const; + virtual QList supportedPaperSizes(const QPrinterInfo &) const; virtual QList > supportedSizesWithNames(const QPrinterInfo &printerInfo) const; virtual QList availablePrinters(); @@ -88,6 +97,7 @@ protected: static QPrinterInfo createPrinterInfo(const QString &name, const QString &description, const QString &location, const QString &makeAndModel, bool isDefault, int index); + static QPrintDevice createPrintDevice(QPlatformPrintDevice *device); QList m_printers; }; diff --git a/src/printsupport/kernel/qprint_p.h b/src/printsupport/kernel/qprint_p.h new file mode 100644 index 0000000000..30f7c4a65e --- /dev/null +++ b/src/printsupport/kernel/qprint_p.h @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPrintSupport 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINT_P_H +#define QPRINT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include +#include + +#if (defined Q_OS_MAC && !defined Q_OS_IOS) || (defined Q_OS_UNIX && !defined QT_NO_CUPS) +#include // Use for type defs only, don't want to actually link in main module +#endif + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PRINTER + +// From windgdi.h +#define DMBIN_UPPER 1 +#define DMBIN_ONLYONE 1 +#define DMBIN_LOWER 2 +#define DMBIN_MIDDLE 3 +#define DMBIN_MANUAL 4 +#define DMBIN_ENVELOPE 5 +#define DMBIN_ENVMANUAL 6 +#define DMBIN_AUTO 7 +#define DMBIN_TRACTOR 8 +#define DMBIN_SMALLFMT 9 +#define DMBIN_LARGEFMT 10 +#define DMBIN_LARGECAPACITY 11 +#define DMBIN_CASSETTE 14 +#define DMBIN_FORMSOURCE 15 +#define DMBIN_USER 256 + +namespace QPrint { + + // Note: Keep in sync with QPrinter::PrinterState for now + // Replace later with more detailed status reporting + enum DeviceState { + Idle, + Active, + Aborted, + Error + }; + + // Note: Keep in sync with QPrinter::DuplexMode + enum DuplexMode { + DuplexNone = 0, + DuplexAuto, + DuplexLongSide, + DuplexShortSide + }; + + enum ColorMode { + GrayScale, + Color + }; + + // Note: Keep in sync with QPrinter::PaperSource for now + // If/when made public, rearrange and rename + enum InputSlotId { + Upper, + Lower, + Middle, + Manual, + Envelope, + EnvelopeManual, + Auto, + Tractor, + SmallFormat, + LargeFormat, + LargeCapacity, + Cassette, + FormSource, + MaxPageSource, // Deprecated, kept for compatibility to QPrinter + CustomInputSlot, + LastInputSlot = CustomInputSlot, + OnlyOne = Upper + }; + + struct InputSlot { + QByteArray key; + QString name; + QPrint::InputSlotId id; + int windowsId; + }; + + enum OutputBinId { + AutoOutputBin, + UpperBin, + LowerBin, + RearBin, + CustomOutputBin, + LastOutputBin = CustomOutputBin + }; + + struct OutputBin { + QByteArray key; + QString name; + QPrint::OutputBinId id; + }; + +}; + +struct InputSlotMap { + QPrint::InputSlotId id; + int windowsId; + const char *key; +}; + +// Note: PPD standard does not define a standard set of InputSlot keywords, +// it is a free form text field left to the PPD writer to decide, +// but it does suggest some names for consistency with the Windows enum. +static const InputSlotMap inputSlotMap[] = { + { QPrint::Upper, DMBIN_UPPER, "Upper" }, + { QPrint::Lower, DMBIN_LOWER, "Lower" }, + { QPrint::Middle, DMBIN_MIDDLE, "Middle" }, + { QPrint::Manual, DMBIN_MANUAL, "Manual" }, + { QPrint::Envelope, DMBIN_ENVELOPE, "Envelope" }, + { QPrint::EnvelopeManual, DMBIN_ENVMANUAL, "EnvelopeManual" }, + { QPrint::Auto, DMBIN_AUTO, "Auto" }, + { QPrint::Tractor, DMBIN_TRACTOR, "Tractor" }, + { QPrint::SmallFormat, DMBIN_SMALLFMT, "AnySmallFormat" }, + { QPrint::LargeFormat, DMBIN_LARGEFMT, "AnyLargeFormat" }, + { QPrint::LargeCapacity, DMBIN_LARGECAPACITY, "LargeCapacity" }, + { QPrint::Cassette, DMBIN_CASSETTE, "Cassette" }, + { QPrint::FormSource, DMBIN_FORMSOURCE, "FormSource" }, + { QPrint::Manual, DMBIN_MANUAL, "ManualFeed" }, + { QPrint::OnlyOne, DMBIN_ONLYONE, "OnlyOne" }, // = QPrint::Upper + { QPrint::CustomInputSlot, DMBIN_USER, "" } // Must always be last row +}; + +struct OutputBinMap { + QPrint::OutputBinId id; + const char *key; +}; + +static const OutputBinMap outputBinMap[] = { + { QPrint::AutoOutputBin, "" }, // Not a PPD defined value, internal use only + { QPrint::UpperBin, "Upper" }, + { QPrint::LowerBin, "Lower" }, + { QPrint::RearBin, "Rear" }, + { QPrint::CustomOutputBin, "" } // Must always be last row +}; + +// Print utilities shared by print plugins + +class QPrintUtils +{ + +public: + + static QPrint::InputSlotId inputSlotKeyToInputSlotId(const QByteArray &key) + { + for (int i = 0; inputSlotMap[i].id != QPrint::CustomInputSlot; ++i) { + if (inputSlotMap[i].key == key) + return inputSlotMap[i].id; + } + return QPrint::CustomInputSlot; + } + + static QByteArray inputSlotIdToInputSlotKey(QPrint::InputSlotId id) + { + for (int i = 0; inputSlotMap[i].id != QPrint::CustomInputSlot; ++i) { + if (inputSlotMap[i].id == id) + return QByteArray(inputSlotMap[i].key); + } + return QByteArray(); + } + + static int inputSlotIdToWindowsId(QPrint::InputSlotId id) + { + for (int i = 0; inputSlotMap[i].id != QPrint::CustomInputSlot; ++i) { + if (inputSlotMap[i].id == id) + return inputSlotMap[i].windowsId; + } + return 0; + } + + static QPrint::OutputBinId outputBinKeyToOutputBinId(const QByteArray &key) + { + for (int i = 0; outputBinMap[i].id != QPrint::CustomOutputBin; ++i) { + if (outputBinMap[i].key == key) + return outputBinMap[i].id; + } + return QPrint::CustomOutputBin; + } + + static QByteArray outputBinIdToOutputBinKey(QPrint::OutputBinId id) + { + for (int i = 0; outputBinMap[i].id != QPrint::CustomOutputBin; ++i) { + if (outputBinMap[i].id == id) + return QByteArray(outputBinMap[i].key); + } + return QByteArray(); + } + +#if (defined Q_OS_MAC && !defined Q_OS_IOS) || (defined Q_OS_UNIX && !defined QT_NO_CUPS) + + // PPD utilities shared by CUPS and Mac plugins requiring CUPS headers + // May turn into a proper internal QPpd class if enough shared between Mac and CUPS, + // but where would it live? Not in base module as don't want to link to CUPS. + // May have to have two copies in plugins to keep in sync. + + static QPrint::InputSlot ppdChoiceToInputSlot(ppd_choice_t choice) + { + QPrint::InputSlot input; + input.key = choice.choice; + input.name = QString::fromUtf8(choice.text); + input.id = inputSlotKeyToInputSlotId(input.key); + input.windowsId = inputSlotMap[input.id].windowsId; + return input; + } + + static QPrint::OutputBin ppdChoiceToOutputBin(ppd_choice_t choice) + { + QPrint::OutputBin output; + output.key = choice.choice; + output.name = QString::fromUtf8(choice.text); + output.id = outputBinKeyToOutputBinId(output.key); + return output; + } + + static int parsePpdResolution(const QByteArray &value) + { + if (value.isEmpty()) + return -1; + // value can be in form 600dpi or 600x600dpi + QByteArray result = value.split('x').at(0); + if (result.endsWith("dpi")) + result.chop(3); + return result.toInt(); + } + + static QPrint::DuplexMode ppdChoiceToDuplexMode(const QByteArray &choice) + { + if (choice == QByteArrayLiteral("DuplexTumble")) + return QPrint::DuplexShortSide; + else if (choice == QByteArrayLiteral("DuplexNoTumble")) + return QPrint::DuplexLongSide; + else // None or SimplexTumble or SimplexNoTumble + return QPrint::DuplexNone; + } + +#endif // Mac and CUPS PPD Utilities + +}; + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE + +#endif // QPRINT_P_H diff --git a/src/printsupport/kernel/qprintdevice.cpp b/src/printsupport/kernel/qprintdevice.cpp new file mode 100644 index 0000000000..c4ba12e0b0 --- /dev/null +++ b/src/printsupport/kernel/qprintdevice.cpp @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPrintSupport 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qprintdevice_p.h" +#include "qplatformprintdevice.h" + +QT_BEGIN_NAMESPACE + +QPrintDevice::QPrintDevice() + : d(new QPlatformPrintDevice()) +{ +} + +QPrintDevice::QPrintDevice(const QString &id) + : d(new QPlatformPrintDevice(id)) +{ +} + +QPrintDevice::QPrintDevice(QPlatformPrintDevice *dd) + : d(dd) +{ +} + +QPrintDevice::QPrintDevice(const QPrintDevice &other) + : d(other.d) +{ +} + +QPrintDevice::~QPrintDevice() +{ +} + +QPrintDevice &QPrintDevice::operator=(const QPrintDevice &other) +{ + d = other.d; + return *this; +} + +bool QPrintDevice::operator==(const QPrintDevice &other) const +{ + if (d && other.d) + return *d == *other.d; + return d == other.d; +} + +QString QPrintDevice::id() const +{ + return isValid() ? d->id() : QString(); +} + +QString QPrintDevice::name() const +{ + return isValid() ? d->name() : QString(); +} + +QString QPrintDevice::location() const +{ + return isValid() ? d->location() : QString(); +} + +QString QPrintDevice::makeAndModel() const +{ + return isValid() ? d->makeAndModel() : QString(); +} + +bool QPrintDevice::isValid() const +{ + return d && d->isValid(); +} + +bool QPrintDevice::isDefault() const +{ + return isValid() && d->isDefault(); +} + +bool QPrintDevice::isRemote() const +{ + return isValid() && d->isRemote(); +} + +QPrint::DeviceState QPrintDevice::state() const +{ + return isValid() ? d->state() : QPrint::Error; +} + +bool QPrintDevice::isValidPageLayout(const QPageLayout &layout, int resolution) const +{ + return isValid() && d->isValidPageLayout(layout, resolution); +} + +bool QPrintDevice::supportsMultipleCopies() const +{ + return isValid() && d->supportsMultipleCopies(); +} + +bool QPrintDevice::supportsCollateCopies() const +{ + return isValid() && d->supportsCollateCopies(); +} + +QPageSize QPrintDevice::defaultPageSize() const +{ + return isValid() ? d->defaultPageSize() : QPageSize(); +} + +QList QPrintDevice::supportedPageSizes() const +{ + return isValid() ? d->supportedPageSizes() : QList(); +} + +QPageSize QPrintDevice::supportedPageSize(const QPageSize &pageSize) const +{ + return isValid() ? d->supportedPageSize(pageSize) : QPageSize(); +} + +QPageSize QPrintDevice::supportedPageSize(QPageSize::PageSizeId pageSizeId) const +{ + return isValid() ? d->supportedPageSize(pageSizeId) : QPageSize(); +} + +QPageSize QPrintDevice::supportedPageSize(const QString &pageName) const +{ + return isValid() ? d->supportedPageSize(pageName) : QPageSize(); +} + +QPageSize QPrintDevice::supportedPageSize(const QSize &pointSize) const +{ + return isValid() ? d->supportedPageSize(pointSize) : QPageSize(); +} + +QPageSize QPrintDevice::supportedPageSize(const QSizeF &size, QPageSize::Unit units) const +{ + return isValid() ? d->supportedPageSize(size, units) : QPageSize(); +} + +bool QPrintDevice::supportsCustomPageSizes() const +{ + return isValid() && d->supportsCustomPageSizes(); +} + +QSize QPrintDevice::minimumPhysicalPageSize() const +{ + return isValid() ? d->minimumPhysicalPageSize() : QSize(); +} + +QSize QPrintDevice::maximumPhysicalPageSize() const +{ + return isValid() ? d->maximumPhysicalPageSize() : QSize(); +} + +QMarginsF QPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + return isValid() ? d->printableMargins(pageSize, orientation, resolution) : QMarginsF(); +} + +int QPrintDevice::defaultResolution() const +{ + return isValid() ? d->defaultResolution() : 0; +} + +QList QPrintDevice::supportedResolutions() const +{ + return isValid() ? d->supportedResolutions() : QList(); +} + +QPrint::InputSlot QPrintDevice::defaultInputSlot() const +{ + return isValid() ? d->defaultInputSlot() : QPrint::InputSlot(); +} + +QList QPrintDevice::supportedInputSlots() const +{ + return isValid() ? d->supportedInputSlots() : QList(); +} + +QPrint::OutputBin QPrintDevice::defaultOutputBin() const +{ + return isValid() ? d->defaultOutputBin() : QPrint::OutputBin(); +} + +QList QPrintDevice::supportedOutputBins() const +{ + return isValid() ? d->supportedOutputBins() : QList(); +} + +QPrint::DuplexMode QPrintDevice::defaultDuplexMode() const +{ + return isValid() ? d->defaultDuplexMode() : QPrint::DuplexNone; +} + +QList QPrintDevice::supportedDuplexModes() const +{ + return isValid() ? d->supportedDuplexModes() : QList(); +} + +QPrint::ColorMode QPrintDevice::defaultColorMode() const +{ + return isValid() ? d->defaultColorMode() : QPrint::GrayScale; +} + +QList QPrintDevice::supportedColorModes() const +{ + return isValid() ? d->supportedColorModes() : QList(); +} + +QList QPrintDevice::supportedMimeTypes() const +{ + return isValid() ? d->supportedMimeTypes() : QList(); +} + +QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h new file mode 100644 index 0000000000..55124c16d4 --- /dev/null +++ b/src/printsupport/kernel/qprintdevice_p.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPrintSupport 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTDEVICE_H +#define QPRINTDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "private/qprint_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlatformPrintDevice; +class QMarginsF; +class QMimeType; + +class Q_PRINTSUPPORT_EXPORT QPrintDevice +{ +public: + + QPrintDevice(); + QPrintDevice(const QString & id); + QPrintDevice(const QPrintDevice &other); + ~QPrintDevice(); + + QPrintDevice &operator=(const QPrintDevice &other); + #ifdef Q_COMPILER_RVALUE_REFS + QPrintDevice &operator=(QPrintDevice &&other) { swap(other); return *this; } +#endif + + void swap(QPrintDevice &other) { d.swap(other.d); } + + bool operator==(const QPrintDevice &other) const; + + QString id() const; + QString name() const; + QString location() const; + QString makeAndModel() const; + + bool isValid() const; + bool isDefault() const; + bool isRemote() const; + + QPrint::DeviceState state() const; + + bool isValidPageLayout(const QPageLayout &layout, int resolution) const; + + bool supportsMultipleCopies() const; + bool supportsCollateCopies() const; + + QPageSize defaultPageSize() const; + QList supportedPageSizes() const; + + QPageSize supportedPageSize(const QPageSize &pageSize) const; + QPageSize supportedPageSize(QPageSize::PageSizeId pageSizeId) const; + QPageSize supportedPageSize(const QString &pageName) const; + QPageSize supportedPageSize(const QSize &pointSize) const; + QPageSize supportedPageSize(const QSizeF &size, QPageSize::Unit units = QPageSize::Point) const; + + bool supportsCustomPageSizes() const; + + QSize minimumPhysicalPageSize() const; + QSize maximumPhysicalPageSize() const; + + QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, int resolution) const; + + int defaultResolution() const; + QList supportedResolutions() const; + + QPrint::InputSlot defaultInputSlot() const; + QList supportedInputSlots() const; + + QPrint::OutputBin defaultOutputBin() const; + QList supportedOutputBins() const; + + QPrint::DuplexMode defaultDuplexMode() const; + QList supportedDuplexModes() const; + + QPrint::ColorMode defaultColorMode() const; + QList supportedColorModes() const; + + QList supportedMimeTypes() const; + +private: + friend class QPlatformPrinterSupport; + friend class QPlatformPrintDevice; + QPrintDevice(QPlatformPrintDevice *dd); + QSharedDataPointer d; +}; + +Q_DECLARE_SHARED(QPrintDevice) + +QT_END_NAMESPACE + +#endif // QPLATFORMPRINTDEVICE_H -- cgit v1.2.3 From 6826912f605f31c8e13bfd84127fd6676602d5f1 Mon Sep 17 00:00:00 2001 From: John Layt Date: Thu, 12 Dec 2013 18:44:27 +0100 Subject: QPlatformPrintDevice - Add CUPS implementation Add support to the CUPS print plugin for the new QPlatformPrintDevice class. Note this is called QPpdPrintDevicePrivate as it uses the CUPS PPD support which is deprecated from CUPS 1.6 onwards. A different plugin will be implemented for the CUPS 1.6 support. Change-Id: I26d005f90842d9c6262341171ef157536d28cc5d Reviewed-by: Lars Knoll --- src/plugins/printsupport/cups/cups.pro | 4 + .../printsupport/cups/qcupsprintersupport.cpp | 41 ++ .../printsupport/cups/qcupsprintersupport_p.h | 7 + src/plugins/printsupport/cups/qppdprintdevice.cpp | 499 +++++++++++++++++++++ src/plugins/printsupport/cups/qppdprintdevice.h | 125 ++++++ 5 files changed, 676 insertions(+) create mode 100644 src/plugins/printsupport/cups/qppdprintdevice.cpp create mode 100644 src/plugins/printsupport/cups/qppdprintdevice.h (limited to 'src') diff --git a/src/plugins/printsupport/cups/cups.pro b/src/plugins/printsupport/cups/cups.pro index f617738a94..cdbb08b10a 100644 --- a/src/plugins/printsupport/cups/cups.pro +++ b/src/plugins/printsupport/cups/cups.pro @@ -6,13 +6,17 @@ load(qt_plugin) QT += core-private gui-private printsupport printsupport-private +LIBS_PRIVATE += -lcups + INCLUDEPATH += ../../../printsupport/kernel SOURCES += main.cpp \ + qppdprintdevice.cpp \ qcupsprintersupport.cpp \ qcupsprintengine.cpp HEADERS += qcupsprintersupport_p.h \ + qppdprintdevice.h \ qcupsprintengine_p.h OTHER_FILES += cups.json diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp index b9f0c394f8..0db448f4bf 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp +++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 John Layt ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -44,7 +45,9 @@ #ifndef QT_NO_PRINTER #include "qcupsprintengine_p.h" +#include "qppdprintdevice.h" #include +#include #include @@ -80,6 +83,44 @@ QPaintEngine *QCupsPrinterSupport::createPaintEngine(QPrintEngine *engine, QPrin return static_cast(engine); } +QPrintDevice QCupsPrinterSupport::createPrintDevice(const QString &id) +{ + return QPlatformPrinterSupport::createPrintDevice(new QPpdPrintDevice(id)); +} + +QStringList QCupsPrinterSupport::availablePrintDeviceIds() const +{ + QStringList list; + cups_dest_t *dests; + int count = cupsGetDests(&dests); + for (int i = 0; i < count; ++i) { + QString printerId = QString::fromLocal8Bit(dests[i].name); + if (dests[i].instance) + printerId += QLatin1Char('/') + QString::fromLocal8Bit(dests[i].instance); + list.append(printerId); + } + cupsFreeDests(count, dests); + return list; +} + +QString QCupsPrinterSupport::defaultPrintDeviceId() const +{ + QString printerId; + cups_dest_t *dests; + int count = cupsGetDests(&dests); + for (int i = 0; i < count; ++i) { + if (dests[i].is_default) { + printerId = QString::fromLocal8Bit(dests[i].name); + if (dests[i].instance) { + printerId += QLatin1Char('/') + QString::fromLocal8Bit(dests[i].instance); + break; + } + } + } + cupsFreeDests(count, dests); + return printerId; +} + QList QCupsPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const { return QCUPSSupport::getCupsPrinterPaperSizes(printerIndex(printerInfo)); diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h index d42c0d2630..9ae4a2cd58 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h +++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 John Layt ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -66,8 +67,14 @@ public: virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode); + + QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; + QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; + QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; + virtual QList supportedPaperSizes(const QPrinterInfo &) const; virtual QList > supportedSizesWithNames(const QPrinterInfo &) const; + virtual QList availablePrinters(); virtual QString printerOption(const QPrinterInfo &printer, const QString &key) const; virtual PrinterOptions printerOptions(const QPrinterInfo &printer) const; diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp new file mode 100644 index 0000000000..fb2d34ed26 --- /dev/null +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -0,0 +1,499 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qppdprintdevice.h" + +#include +#include + +#ifndef QT_LINUXBASE // LSB merges everything into cups.h +#include +#endif + +QT_BEGIN_NAMESPACE + +QPpdPrintDevice::QPpdPrintDevice() + : QPlatformPrintDevice(), + m_cupsDest(0), + m_ppd(0) +{ +} + +QPpdPrintDevice::QPpdPrintDevice(const QString &id) + : QPlatformPrintDevice(id), + m_cupsDest(0), + m_ppd(0) +{ + if (!id.isEmpty()) { + + // TODO For now each dest is an individual device + QStringList parts = id.split(QLatin1Char('/')); + m_cupsName = parts.at(0).toUtf8(); + if (parts.size() > 1) + m_cupsInstance = parts.at(1).toUtf8(); + loadPrinter(); + + if (m_cupsDest && m_ppd) { + m_name = printerOption("printer-info"); + m_location = printerOption("printer-location"); + m_makeAndModel = printerOption("printer-make-and-model"); + cups_ptype_e type = printerTypeFlags(); + m_isRemote = type & CUPS_PRINTER_REMOTE; + // Note this is if the hardware does multiple copies, not if Cups can + m_supportsMultipleCopies = type & CUPS_PRINTER_COPIES; + // Note this is if the hardware does collation, not if Cups can + m_supportsCollateCopies = type & CUPS_PRINTER_COLLATE; + + // Custom Page Size support + // Cups cups_ptype_e CUPS_PRINTER_VARIABLE + // Cups ppd_file_t variable_sizes custom_min custom_max + // PPD MaxMediaWidth MaxMediaHeight + m_supportsCustomPageSizes = type & CUPS_PRINTER_VARIABLE; + m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]); + m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]); + m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3], + m_ppd->custom_margins[2], m_ppd->custom_margins[1]); + } + } +} + +QPpdPrintDevice::QPpdPrintDevice(const QPpdPrintDevice &other) + : QPlatformPrintDevice(other), + m_cupsDest(0), + m_ppd(0) +{ + m_cupsName = other.m_cupsName; + m_cupsInstance = other.m_cupsInstance; + loadPrinter(); +} + +QPpdPrintDevice::~QPpdPrintDevice() +{ + if (m_ppd) + ppdClose(m_ppd); + if (m_cupsDest) + cupsFreeDests(1, m_cupsDest); + m_cupsDest = 0; + m_ppd = 0; +} + +QPpdPrintDevice &QPpdPrintDevice::operator=(const QPpdPrintDevice &other) +{ + m_cupsName = other.m_cupsName; + m_cupsInstance = other.m_cupsInstance; + if (other.m_cupsDest && other.m_ppd) + loadPrinter(); + return *this; +} + +bool QPpdPrintDevice::operator==(const QPpdPrintDevice &other) const +{ + return (m_id == other.m_id); +} + +bool QPpdPrintDevice::isValid() const +{ + return m_cupsDest && m_ppd; +} + +bool QPpdPrintDevice::isDefault() const +{ + return printerTypeFlags() & CUPS_PRINTER_DEFAULT; +} + +QPrint::DeviceState QPpdPrintDevice::state() const +{ + // 3 = idle, 4 = printing, 5 = stopped + // More details available from printer-state-message and printer-state-reasons + int state = printerOption(QStringLiteral("printer-state")).toInt(); + if (state == 3) + return QPrint::Idle; + else if (state == 4) + return QPrint::Active; + else + return QPrint::Error; +} + +void QPpdPrintDevice::loadPageSizes() const +{ + m_pageSizes.clear(); + m_printableMargins.clear(); + + ppd_option_t *pageSizes = ppdFindOption(m_ppd, "PageSize"); + if (pageSizes) { + for (int i = 0; i < pageSizes->num_choices; ++i) { + const ppd_size_t *ppdSize = ppdPageSize(m_ppd, pageSizes->choices[i].choice); + if (ppdSize) { + // Returned size is in points + QString key = QString::fromUtf8(ppdSize->name); + QSize size = QSize(qRound(ppdSize->width), qRound(ppdSize->length)); + QString name = QString::fromUtf8(pageSizes->choices[i].text); + if (!size.isEmpty()) { + QPageSize ps = createPageSize(key, size, name); + if (ps.isValid()) { + m_pageSizes.append(ps); + m_printableMargins.insert(key, QMarginsF(ppdSize->left, ppdSize->length - ppdSize->top, + ppdSize->width - ppdSize->right, ppdSize->bottom)); + } + } + } + } + m_havePageSizes = true; + } +} + +QPageSize QPpdPrintDevice::defaultPageSize() const +{ + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "PageSize"); + if (defaultChoice) { + ppd_size_t *ppdSize = ppdPageSize(m_ppd, defaultChoice->choice); + if (ppdSize) { + // Returned size is in points + QString key = QString::fromUtf8(ppdSize->name); + QSize size = QSize(qRound(ppdSize->width), qRound(ppdSize->length)); + QString name = QString::fromUtf8(defaultChoice->text); + return createPageSize(key, size, name); + } + } + return QPageSize(); +} + +QMarginsF QPpdPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + Q_UNUSED(orientation) + Q_UNUSED(resolution) + if (!m_havePageSizes) + loadPageSizes(); + // TODO Orientation? + if (m_printableMargins.contains(pageSize.key())) + return m_printableMargins.value(pageSize.key()); + return m_customMargins; +} + +void QPpdPrintDevice::loadResolutions() const +{ + m_resolutions.clear(); + + // Try load standard PPD options first + ppd_option_t *resolutions = ppdFindOption(m_ppd, "Resolution"); + if (resolutions) { + for (int i = 0; i < resolutions->num_choices; ++i) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[i].choice); + if (res > 0) + m_resolutions.append(res); + } + } + // If no result, try just the default + if (m_resolutions.size() == 0) { + resolutions = ppdFindOption(m_ppd, "DefaultResolution"); + if (resolutions) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[0].choice); + if (res > 0) + m_resolutions.append(res); + } + } + // If still no result, then try HP's custom options + if (m_resolutions.size() == 0) { + resolutions = ppdFindOption(m_ppd, "HPPrintQuality"); + if (resolutions) { + for (int i = 0; i < resolutions->num_choices; ++i) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[i].choice); + if (res > 0) + m_resolutions.append(res); + } + } + } + if (m_resolutions.size() == 0) { + resolutions = ppdFindOption(m_ppd, "DefaultHPPrintQuality"); + if (resolutions) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[0].choice); + if (res > 0) + m_resolutions.append(res); + } + } + m_haveResolutions = true; +} + +int QPpdPrintDevice::defaultResolution() const +{ + // Try load standard PPD option first + ppd_option_t *resolution = ppdFindOption(m_ppd, "DefaultResolution"); + if (resolution) { + int res = QPrintUtils::parsePpdResolution(resolution->choices[0].choice); + if (res > 0) + return res; + } + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "Resolution"); + if (defaultChoice) { + int res = QPrintUtils::parsePpdResolution(defaultChoice->choice); + if (res > 0) + return res; + } + // If still no result, then try HP's custom options + resolution = ppdFindOption(m_ppd, "DefaultHPPrintQuality"); + if (resolution) { + int res = QPrintUtils::parsePpdResolution(resolution->choices[0].choice); + if (res > 0) + return res; + } + defaultChoice = ppdFindMarkedChoice(m_ppd, "HPPrintQuality"); + if (defaultChoice) { + int res = QPrintUtils::parsePpdResolution(defaultChoice->choice); + if (res > 0) + return res; + } + // Otherwise return a sensible default. + // TODO What is sensible? 150? 300? + return 72; +} + +void QPpdPrintDevice::loadInputSlots() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // TODO Deal with concatenated names like Tray1Manual or Tray1_Man, + // will currently show as CustomInputSlot + // TODO Deal with separate ManualFeed key + // Try load standard PPD options first + m_inputSlots.clear(); + if (m_ppd) { + ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot"); + if (inputSlots) { + for (int i = 0; i < inputSlots->num_choices; ++i) + m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i])); + } + // If no result, try just the default + if (m_inputSlots.size() == 0) { + inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot"); + if (inputSlots) + m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0])); + } + } + // If still no result, just use Auto + if (m_inputSlots.size() == 0) + m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot()); + m_haveInputSlots = true; +} + +QPrint::InputSlot QPpdPrintDevice::defaultInputSlot() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot"); + if (inputSlot) + return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice); + } + // Otherwise return Auto + return QPlatformPrintDevice::defaultInputSlot(); +} + +void QPpdPrintDevice::loadOutputBins() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + m_outputBins.clear(); + if (m_ppd) { + ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin"); + if (outputBins) { + for (int i = 0; i < outputBins->num_choices; ++i) + m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i])); + } + // If no result, try just the default + if (m_outputBins.size() == 0) { + outputBins = ppdFindOption(m_ppd, "DefaultOutputBin"); + if (outputBins) + m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0])); + } + } + // If still no result, just use Auto + if (m_outputBins.size() == 0) + m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); + m_haveOutputBins = true; +} + +QPrint::OutputBin QPpdPrintDevice::defaultOutputBin() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin"); + if (outputBin) + return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice); + } + // Otherwise return AutoBin + return QPlatformPrintDevice::defaultOutputBin(); +} + +void QPpdPrintDevice::loadDuplexModes() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD options first + m_duplexModes.clear(); + if (m_ppd) { + ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex"); + if (duplexModes) { + for (int i = 0; i < duplexModes->num_choices; ++i) + m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice)); + } + // If no result, try just the default + if (m_duplexModes.size() == 0) { + duplexModes = ppdFindOption(m_ppd, "DefaultDuplex"); + if (duplexModes) + m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice)); + } + } + // If still no result, or not added in PPD, then add None + if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) + m_duplexModes.append(QPrint::DuplexNone); + m_haveDuplexModes = true; +} + +QPrint::DuplexMode QPpdPrintDevice::defaultDuplexMode() const +{ + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultDuplex"); + if (inputSlot) + return QPrintUtils::ppdChoiceToDuplexMode(inputSlot->choices[0].choice); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "Duplex"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToDuplexMode(defaultChoice->choice); + } + // Otherwise return None + return QPrint::DuplexNone; +} + +void QPpdPrintDevice::loadColorModes() const +{ + // Cups cups_ptype_e CUPS_PRINTER_BW CUPS_PRINTER_COLOR + // Cups ppd_file_t color_device + // PPD ColorDevice + m_colorModes.clear(); + cups_ptype_e type = printerTypeFlags(); + if (type & CUPS_PRINTER_BW) + m_colorModes.append(QPrint::GrayScale); + if (type & CUPS_PRINTER_COLOR) + m_colorModes.append(QPrint::Color); + m_haveColorModes = true; +} + +QPrint::ColorMode QPpdPrintDevice::defaultColorMode() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Not a proper option, usually only know if supports color or not, but some + // users known to abuse ColorModel to always force GrayScale. + if (m_ppd && supportedColorModes().contains(QPrint::Color)) { + ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel"); + if (!colorModel) + colorModel = ppdFindOption(m_ppd, "ColorModel"); + if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray"))) + return QPrint::Color; + } + return QPrint::GrayScale; +} + +void QPpdPrintDevice::loadMimeTypes() const +{ + // TODO No CUPS api? Need to manually load CUPS mime.types file? + // For now hard-code most common support types + QMimeDatabase db; + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/pdf"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/postscript"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/gif"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/png"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/jpeg"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/tiff"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/html"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/plain"))); + m_haveMimeTypes = true; +} + +void QPpdPrintDevice::loadPrinter() +{ + // Just to be safe, check if existing printer needs closing + if (m_ppd) { + ppdClose(m_ppd); + m_ppd = 0; + } + if (m_cupsDest) { + cupsFreeDests(1, m_cupsDest); + m_cupsDest = 0; + } + + // Get the print instance and PPD file + m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance); + if (m_cupsDest) { + const char *ppdFile = cupsGetPPD(m_cupsName); + if (ppdFile) + m_ppd = ppdOpenFile(ppdFile); + unlink(ppdFile); + if (m_ppd) { + ppdMarkDefaults(m_ppd); + } else { + cupsFreeDests(1, m_cupsDest); + m_cupsDest = 0; + m_ppd = 0; + } + } +} + +QString QPpdPrintDevice::printerOption(const QString &key) const +{ + return cupsGetOption(key.toUtf8(), m_cupsDest->num_options, m_cupsDest->options); +} + +cups_ptype_e QPpdPrintDevice::printerTypeFlags() const +{ + return static_cast(printerOption("printer-type").toUInt()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h new file mode 100644 index 0000000000..cdea40dd6d --- /dev/null +++ b/src/plugins/printsupport/cups/qppdprintdevice.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPPDPRINTDEVICE_H +#define QPPDPRINTDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include // Some feature dependencies might define QT_NO_PRINTER +#ifndef QT_NO_PRINTER + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPpdPrintDevice : public QPlatformPrintDevice +{ +public: + QPpdPrintDevice(); + explicit QPpdPrintDevice(const QString &id); + QPpdPrintDevice(const QPpdPrintDevice &other); + virtual ~QPpdPrintDevice(); + + QPpdPrintDevice &operator=(const QPpdPrintDevice &other); + + QPpdPrintDevice *clone(); + + bool operator==(const QPpdPrintDevice &other) const; + + bool isValid() const Q_DECL_OVERRIDE; + bool isDefault() const Q_DECL_OVERRIDE; + + QPrint::DeviceState state() const Q_DECL_OVERRIDE; + + QPageSize defaultPageSize() const Q_DECL_OVERRIDE; + + QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, + int resolution) const Q_DECL_OVERRIDE; + + int defaultResolution() const Q_DECL_OVERRIDE; + + QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE; + + QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE; + + QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE; + + QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE; + +protected: + void loadPageSizes() const Q_DECL_OVERRIDE; + void loadResolutions() const Q_DECL_OVERRIDE; + void loadInputSlots() const Q_DECL_OVERRIDE; + void loadOutputBins() const Q_DECL_OVERRIDE; + void loadDuplexModes() const Q_DECL_OVERRIDE; + void loadColorModes() const Q_DECL_OVERRIDE; + void loadMimeTypes() const Q_DECL_OVERRIDE; + +private: + void loadPrinter(); + QString printerOption(const QString &key) const; + cups_ptype_e printerTypeFlags() const; + + cups_dest_t *m_cupsDest; + ppd_file_t *m_ppd; + QByteArray m_cupsName; + QByteArray m_cupsInstance; + QMarginsF m_customMargins; + mutable QHash m_printableMargins; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER +#endif // QPPDPRINTDEVICE_H -- cgit v1.2.3 From e33b9152678cd62a7f314dae80898326595c86c0 Mon Sep 17 00:00:00 2001 From: John Layt Date: Tue, 17 Dec 2013 15:46:34 +0100 Subject: QPlatformPrintDevice - Add Mac implementation Implement the OSX support for QPlatformPrintDevice Change-Id: I2e3900818d4d9f0682a15ed94b8c824085adb465 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/cocoa.pro | 4 +- src/plugins/platforms/cocoa/qcocoaprintdevice.h | 130 ++++++ src/plugins/platforms/cocoa/qcocoaprintdevice.mm | 498 +++++++++++++++++++++ src/plugins/platforms/cocoa/qcocoaprintersupport.h | 4 + .../platforms/cocoa/qcocoaprintersupport.mm | 35 ++ 5 files changed, 670 insertions(+), 1 deletion(-) create mode 100644 src/plugins/platforms/cocoa/qcocoaprintdevice.h create mode 100644 src/plugins/platforms/cocoa/qcocoaprintdevice.mm (limited to 'src') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index d8cd32255c..a60f4adc28 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -81,7 +81,7 @@ HEADERS += qcocoaintegration.h \ RESOURCES += qcocoaresources.qrc -LIBS += -framework Cocoa -framework Carbon -framework IOKit +LIBS += -framework Cocoa -framework Carbon -framework IOKit -lcups QT += core-private gui-private platformsupport-private @@ -90,11 +90,13 @@ qtHaveModule(widgets) { qpaintengine_mac.mm \ qprintengine_mac.mm \ qcocoaprintersupport.mm \ + qcocoaprintdevice.mm \ HEADERS += \ qpaintengine_mac_p.h \ qprintengine_mac_p.h \ qcocoaprintersupport.h \ + qcocoaprintdevice.h \ QT += widgets-private printsupport-private } diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h new file mode 100644 index 0000000000..3f1fa475d5 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOAPRINTDEVICE_H +#define QCOCOAPRINTDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include // Some feature dependencies might define QT_NO_PRINTER +#ifndef QT_NO_PRINTER + +#include + +#include "qt_mac_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QCocoaPrintDevice : public QPlatformPrintDevice +{ +public: + QCocoaPrintDevice(); + explicit QCocoaPrintDevice(const QString &id); + QCocoaPrintDevice(const QCocoaPrintDevice &other); + virtual ~QCocoaPrintDevice(); + + QCocoaPrintDevice *clone(); + + bool operator==(const QCocoaPrintDevice &other) const; + + bool isValid() const Q_DECL_OVERRIDE; + bool isDefault() const Q_DECL_OVERRIDE; + + QPrint::DeviceState state() const Q_DECL_OVERRIDE; + + QPageSize defaultPageSize() const Q_DECL_OVERRIDE; + + QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, + int resolution) const Q_DECL_OVERRIDE; + + int defaultResolution() const Q_DECL_OVERRIDE; + + QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE; + + QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE; + + QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE; + + QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE; + + PMPrinter macPrinter() const; + PMPaper macPaper(const QPageSize &pageSize) const; + +protected: + void loadPageSizes() const Q_DECL_OVERRIDE; + void loadResolutions() const Q_DECL_OVERRIDE; + void loadInputSlots() const Q_DECL_OVERRIDE; + void loadOutputBins() const Q_DECL_OVERRIDE; + void loadDuplexModes() const Q_DECL_OVERRIDE; + void loadColorModes() const Q_DECL_OVERRIDE; + void loadMimeTypes() const Q_DECL_OVERRIDE; + +private: + QPageSize createPageSize(const PMPaper &paper) const; + bool openPpdFile(); + + // Mac Core Printing + PMPrinter m_printer; + PMPrintSession m_session; + mutable QHash m_macPapers; + + // PPD File + ppd_file_t *m_ppd; + + QMarginsF m_customMargins; + mutable QHash m_printableMargins; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER +#endif // QCOCOAPRINTDEVICE_H diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm new file mode 100644 index 0000000000..d8b01ec07f --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -0,0 +1,498 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcocoaprintdevice.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode) +{ + if (mode == kPMDuplexTumble) + return QPrint::DuplexShortSide; + else if (mode == kPMDuplexNoTumble) + return QPrint::DuplexLongSide; + else // kPMDuplexNone or kPMSimplexTumble + return QPrint::DuplexNone; +} + +QCocoaPrintDevice::QCocoaPrintDevice() + : QPlatformPrintDevice(), + m_printer(0), + m_session(0), + m_ppd(0) +{ +} + +QCocoaPrintDevice::QCocoaPrintDevice(const QString &id) + : QPlatformPrintDevice(id), + m_printer(0), + m_session(0), + m_ppd(0) +{ + if (!id.isEmpty()) { + m_printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(id)); + if (m_printer) { + m_name = QCFString::toQString(PMPrinterGetName(m_printer)); + m_location = QCFString::toQString(PMPrinterGetLocation(m_printer)); + CFStringRef cfMakeAndModel; + if (PMPrinterGetMakeAndModelName(m_printer, &cfMakeAndModel) == noErr) + m_makeAndModel = QCFString::toQString(cfMakeAndModel); + Boolean isRemote; + if (PMPrinterIsRemote(m_printer, &isRemote) == noErr) + m_isRemote = isRemote; + if (PMCreateSession(&m_session) == noErr) + PMSessionSetCurrentPMPrinter(m_session, m_printer); + + // No native api to query these options, need to use PPD directly, note is deprecated from 1.6 onwards + if (openPpdFile()) { + // Note this is if the hardware does multiple copies, not if Cups can + m_supportsMultipleCopies = !m_ppd->manual_copies; + // Note this is if the hardware does collation, not if Cups can + ppd_option_t *collate = ppdFindOption(m_ppd, "Collate"); + if (collate) + m_supportsCollateCopies = true; + m_supportsCustomPageSizes = m_ppd->custom_max[0] > 0 && m_ppd->custom_max[1] > 0; + m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]); + m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]); + m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3], + m_ppd->custom_margins[2], m_ppd->custom_margins[1]); + } + } + } +} + +QCocoaPrintDevice::QCocoaPrintDevice(const QCocoaPrintDevice &other) + : QPlatformPrintDevice(other), + m_printer(0), + m_session(0), + m_ppd(0) +{ + m_printer = other.m_printer; + PMRetain(m_printer); + m_session = other.m_session; + PMRetain(m_session); + m_macPapers = other.m_macPapers; + foreach (PMPaper paper, m_macPapers.values()) + PMRetain(paper); + openPpdFile(); + m_customMargins = other.m_customMargins; + m_printableMargins = other.m_printableMargins; +} + +QCocoaPrintDevice::~QCocoaPrintDevice() +{ + if (m_ppd) + ppdClose(m_ppd); + foreach (PMPaper paper, m_macPapers.values()) + PMRelease(paper); + // Releasing the session appears to also release the printer + if (m_session) + PMRelease(m_session); + else if (m_printer) + PMRelease(m_printer); +} + +QCocoaPrintDevice *QCocoaPrintDevice::clone() +{ + return new QCocoaPrintDevice(*this); +} + +bool QCocoaPrintDevice::operator==(const QCocoaPrintDevice &other) const +{ + return (m_id == other.m_id); +} + +bool QCocoaPrintDevice::isValid() const +{ + return m_printer ? true : false; +} + +bool QCocoaPrintDevice::isDefault() const +{ + return PMPrinterIsDefault(m_printer); +} + +QPrint::DeviceState QCocoaPrintDevice::state() const +{ + PMPrinterState state; + if (PMPrinterGetState(m_printer, &state) == noErr) { + if (state == kPMPrinterIdle) + return QPrint::Idle; + else if (state == kPMPrinterProcessing) + return QPrint::Active; + else if (state == kPMPrinterStopped) + return QPrint::Error; + } + return QPrint::Error; +} + +QPageSize QCocoaPrintDevice::createPageSize(const PMPaper &paper) const +{ + QCFString key; + double width; + double height; + QCFString localizedName; + if (PMPaperGetPPDPaperName(paper, &key) == noErr + && PMPaperGetWidth(paper, &width) == noErr + && PMPaperGetHeight(paper, &height) == noErr + && PMPaperCreateLocalizedName(paper, m_printer, &localizedName) == noErr) { + return(QPlatformPrintDevice::createPageSize(key, QSize(width, height), localizedName)); + } + return QPageSize(); +} + +void QCocoaPrintDevice::loadPageSizes() const +{ + m_pageSizes.clear(); + foreach (PMPaper paper, m_macPapers.values()) + PMRelease(paper); + m_macPapers.clear(); + m_printableMargins.clear(); + CFArrayRef paperSizes; + if (PMPrinterGetPaperList(m_printer, &paperSizes) == noErr) { + int count = CFArrayGetCount(paperSizes); + for (int i = 0; i < count; ++i) { + PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(paperSizes, i))); + QPageSize pageSize = createPageSize(paper); + if (pageSize.isValid()) { + m_pageSizes.append(pageSize); + PMRetain(paper); + m_macPapers.insert(pageSize.key(), paper); + PMPaperMargins printMargins; + PMPaperGetMargins(paper, &printMargins); + m_printableMargins.insert(pageSize.key(), QMarginsF(printMargins.left, printMargins.top, + printMargins.right, printMargins.bottom)); + } + } + } + m_havePageSizes = true; +} + +QPageSize QCocoaPrintDevice::defaultPageSize() const +{ + QPageSize pageSize; + PMPageFormat pageFormat; + PMPaper paper; + if (PMCreatePageFormat(&pageFormat) == noErr + && PMSessionDefaultPageFormat(m_session, pageFormat) == noErr + && PMGetPageFormatPaper(pageFormat, &paper) == noErr) { + pageSize = createPageSize(paper); + PMRelease(pageFormat); + } + return pageSize; +} + +QMarginsF QCocoaPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + Q_UNUSED(orientation) + Q_UNUSED(resolution) + if (!m_havePageSizes) + loadPageSizes(); + if (m_printableMargins.contains(pageSize.key())) + return m_printableMargins.value(pageSize.key()); + return m_customMargins; +} + +void QCocoaPrintDevice::loadResolutions() const +{ + m_resolutions.clear(); + UInt32 count; + if (PMPrinterGetPrinterResolutionCount(m_printer, &count) == noErr) { + // 1-based index + for (UInt32 i = 1; i <= count; ++i) { + PMResolution resolution; + if (PMPrinterGetIndexedPrinterResolution(m_printer, i, &resolution) == noErr) + m_resolutions.append(int(resolution.hRes)); + } + } + m_haveResolutions = true; +} + +int QCocoaPrintDevice::defaultResolution() const +{ + int defaultResolution = 72; + PMPrintSettings settings; + if (PMCreatePrintSettings(&settings) == noErr) { + PMResolution resolution; + if (PMSessionDefaultPrintSettings(m_session, settings) == noErr + && PMPrinterGetOutputResolution(m_printer, settings, &resolution) == noErr) { + // PMPrinterGetOutputResolution usually fails with -9589 kPMKeyNotFound as not set in PPD + defaultResolution = int(resolution.hRes); + } + PMRelease(settings); + } + // If no value returned (usually means not set in PPD) then use supported resolutions which + // OSX will have populated with at least one default value (but why not returned by call?) + if (defaultResolution <= 0) { + if (!m_haveResolutions) + loadResolutions(); + if (m_resolutions.count() > 0) + return m_resolutions.at(0); // First value or highest? Only likely to be one anyway. + return 72; // TDOD More sensible default value??? + } + return defaultResolution; +} + +void QCocoaPrintDevice::loadInputSlots() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // TODO Deal with concatenated names like Tray1Manual or Tray1_Man, + // will currently show as CustomInputSlot + // TODO Deal with separate ManualFeed key + // Try load standard PPD options first + m_inputSlots.clear(); + if (m_ppd) { + ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot"); + if (inputSlots) { + for (int i = 0; i < inputSlots->num_choices; ++i) + m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i])); + } + // If no result, try just the default + if (m_inputSlots.size() == 0) { + inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot"); + if (inputSlots) + m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0])); + } + } + // If still no result, just use Auto + if (m_inputSlots.size() == 0) + m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot()); + m_haveInputSlots = true; +} + +QPrint::InputSlot QCocoaPrintDevice::defaultInputSlot() const +{ + // No native api to query, use PPD directly + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot"); + if (inputSlot) + return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice); + } + // Otherwise return Auto + return QPlatformPrintDevice::defaultInputSlot(); +} + +void QCocoaPrintDevice::loadOutputBins() const +{ + // No native api to query, use PPD directly + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + m_outputBins.clear(); + if (m_ppd) { + ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin"); + if (outputBins) { + for (int i = 0; i < outputBins->num_choices; ++i) + m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i])); + } + // If no result, try just the default + if (m_outputBins.size() == 0) { + outputBins = ppdFindOption(m_ppd, "DefaultOutputBin"); + if (outputBins) + m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0])); + } + } + // If still no result, just use Auto + if (m_outputBins.size() == 0) + m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); + m_haveOutputBins = true; +} + +QPrint::OutputBin QCocoaPrintDevice::defaultOutputBin() const +{ + // No native api to query, use PPD directly + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin"); + if (outputBin) + return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice); + } + // Otherwise return AutoBin + return QPlatformPrintDevice::defaultOutputBin(); +} + +void QCocoaPrintDevice::loadDuplexModes() const +{ + // No native api to query, use PPD directly + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD options first + m_duplexModes.clear(); + if (m_ppd) { + ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex"); + if (duplexModes) { + for (int i = 0; i < duplexModes->num_choices; ++i) + m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice)); + } + // If no result, try just the default + if (m_duplexModes.size() == 0) { + duplexModes = ppdFindOption(m_ppd, "DefaultDuplex"); + if (duplexModes) + m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice)); + } + } + // If still no result, or not added in PPD, then add None + if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) + m_duplexModes.append(QPrint::DuplexNone); + m_haveDuplexModes = true; +} + +QPrint::DuplexMode QCocoaPrintDevice::defaultDuplexMode() const +{ + QPrint::DuplexMode defaultMode = QPrint::DuplexNone; + PMPrintSettings settings; + if (PMCreatePrintSettings(&settings) == noErr) { + PMDuplexMode duplexMode; + if (PMSessionDefaultPrintSettings(m_session, settings) == noErr + && PMGetDuplex(settings, &duplexMode) == noErr) { + defaultMode = macToDuplexMode(duplexMode); + } + PMRelease(settings); + } + return defaultMode; +} + +void QCocoaPrintDevice::loadColorModes() const +{ + // No native api to query, use PPD directly + m_colorModes.clear(); + m_colorModes.append(QPrint::GrayScale); + if (!m_ppd || (m_ppd && m_ppd->color_device)) + m_colorModes.append(QPrint::Color); + m_haveColorModes = true; +} + +QPrint::ColorMode QCocoaPrintDevice::defaultColorMode() const +{ + // No native api to query, use PPD directly + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Not a proper option, usually only know if supports color or not, but some + // users known to abuse ColorModel to always force GrayScale. + if (m_ppd && supportedColorModes().contains(QPrint::Color)) { + ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel"); + if (!colorModel) + colorModel = ppdFindOption(m_ppd, "ColorModel"); + if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray"))) + return QPrint::Color; + } + return QPrint::GrayScale; +} + +void QCocoaPrintDevice::loadMimeTypes() const +{ + // TODO Check how settings affect returned list + m_mimeTypes.clear(); + QMimeDatabase db; + PMPrintSettings settings; + if (PMCreatePrintSettings(&settings) == noErr) { + CFArrayRef mimeTypes; + if (PMPrinterGetMimeTypes(m_printer, settings, &mimeTypes) == noErr) { + int count = CFArrayGetCount(mimeTypes); + for (int i = 0; i < count; ++i) { + CFStringRef mimeName = static_cast(const_cast(CFArrayGetValueAtIndex(mimeTypes, i))); + QMimeType mimeType = db.mimeTypeForName(QCFString::toQString(mimeName)); + if (mimeType.isValid()) + m_mimeTypes.append(mimeType); + } + } + PMRelease(settings); + } + m_haveMimeTypes = true; +} + +bool QCocoaPrintDevice::openPpdFile() +{ + if (m_ppd) + ppdClose(m_ppd); + m_ppd = 0; + CFURLRef ppdURL = NULL; + char ppdPath[MAXPATHLEN]; + if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr + && ppdURL != NULL + && CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) { + m_ppd = ppdOpenFile(ppdPath); + } + CFRelease(ppdURL); + return m_ppd ? true : false; +} + +PMPrinter QCocoaPrintDevice::macPrinter() const +{ + return m_printer; +} + +// Returns a cached printer PMPaper, or creates and caches a new custom PMPaper +// Caller should never release a cached PMPaper! +PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const +{ + if (!m_havePageSizes) + loadPageSizes(); + // If keys match, then is a supported size or an existing custom size + if (m_macPapers.contains(pageSize.key())) + return m_macPapers.value(pageSize.key()); + // For any other page size, whether custom or just unsupported, needs to be a custom PMPaper + PMPaper paper = 0; + PMPaperMargins paperMargins; + paperMargins.left = m_customMargins.left(); + paperMargins.right = m_customMargins.right(); + paperMargins.top = m_customMargins.top(); + paperMargins.bottom = m_customMargins.bottom(); + PMPaperCreateCustom(m_printer, QCFString(pageSize.key()), QCFString(pageSize.name()), + pageSize.sizePoints().width(), pageSize.sizePoints().height(), + &paperMargins, &paper); + m_macPapers.insert(pageSize.key(), paper); + return paper; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index a48790ef34..4c6a99ec9d 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -58,6 +58,10 @@ public: QList supportedPaperSizes(const QPrinterInfo &) const Q_DECL_OVERRIDE; QList > supportedSizesWithNames(const QPrinterInfo &) const Q_DECL_OVERRIDE; + QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; + QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; + QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; + QList availablePrinters() Q_DECL_OVERRIDE; QPrinterInfo printerInfo(const QString &printerName) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm index cb2aa7132b..70c83498e1 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -42,11 +42,13 @@ #include "qcocoaprintersupport.h" #ifndef QT_NO_PRINTER +#include "qcocoaprintdevice.h" #include "qprintengine_mac_p.h" #include #include #include +#include QCocoaPrinterSupport::QCocoaPrinterSupport() { } @@ -69,6 +71,39 @@ QPaintEngine *QCocoaPrinterSupport::createPaintEngine(QPrintEngine *printEngine, return static_cast(printEngine); } +QPrintDevice QCocoaPrinterSupport::createPrintDevice(const QString &id) +{ + return QPlatformPrinterSupport::createPrintDevice(new QCocoaPrintDevice(id)); +} + +QStringList QCocoaPrinterSupport::availablePrintDeviceIds() const +{ + QStringList list; + QCFType printerList; + if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i = 0; i < count; ++i) { + PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); + list.append(QCFString::toQString(PMPrinterGetID(printer))); + } + } + return list; +} + +QString QCocoaPrinterSupport::defaultPrintDeviceId() const +{ + QCFType printerList; + if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i = 0; i < count; ++i) { + PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); + if (PMPrinterIsDefault(printer)) + return QCFString::toQString(PMPrinterGetID(printer)); + } + } + return QString(); +} + QList QCocoaPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const { QList returnValue; -- cgit v1.2.3 From cf8b8340f3d283830a6aca2f708e839bb70d6d57 Mon Sep 17 00:00:00 2001 From: John Layt Date: Tue, 17 Dec 2013 12:55:32 -0500 Subject: QPlatformPrintDevice - Add Windows implementation Add Windows implementation of QPlatformPrintDevice. Change-Id: I007678cd6d2bdae0728b61cc2796a5c5e5d1578f Reviewed-by: Lars Knoll --- .../printsupport/windows/qwindowsprintdevice.cpp | 472 +++++++++++++++++++++ .../printsupport/windows/qwindowsprintdevice.h | 115 +++++ .../windows/qwindowsprintersupport.cpp | 17 + .../printsupport/windows/qwindowsprintersupport.h | 6 + src/plugins/printsupport/windows/windows.pro | 6 +- 5 files changed, 614 insertions(+), 2 deletions(-) create mode 100644 src/plugins/printsupport/windows/qwindowsprintdevice.cpp create mode 100644 src/plugins/printsupport/windows/qwindowsprintdevice.h (limited to 'src') diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp new file mode 100644 index 0000000000..c45e266aaa --- /dev/null +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -0,0 +1,472 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsprintdevice.h" + +#include + +QT_BEGIN_NAMESPACE + +extern qreal qt_pointMultiplier(QPageLayout::Unit unit); + +static inline uint qwcsnlen(const wchar_t *str, uint maxlen) +{ + uint length = 0; + if (str) { + while (length < maxlen && *str++) + length++; + } + return length; +} + +static QPrint::InputSlot paperBinToInputSlot(int windowsId, const QString &name) +{ + QPrint::InputSlot slot; + slot.name = name; + int i; + for (i = 0; inputSlotMap[i].id != QPrint::CustomInputSlot; ++i) { + if (inputSlotMap[i].windowsId == windowsId) { + slot.key = inputSlotMap[i].key; + slot.id = inputSlotMap[i].id; + slot.windowsId = inputSlotMap[i].windowsId; + return slot; + } + } + slot.key = inputSlotMap[i].key; + slot.id = inputSlotMap[i].id; + return slot; +} + + +QWindowsPrintDevice::QWindowsPrintDevice() + : QPlatformPrintDevice(), + m_hPrinter(0) +{ +} + +QWindowsPrintDevice::QWindowsPrintDevice(const QString &id) + : QPlatformPrintDevice(id), + m_hPrinter(0) +{ + // First do a fast lookup to see if printer exists, if it does then open it + if (!id.isEmpty() && QWindowsPrintDevice::availablePrintDeviceIds().contains(id)) { + if (OpenPrinter((LPWSTR)m_id.utf16(), &m_hPrinter, NULL)) { + DWORD needed = 0; + GetPrinter(m_hPrinter, 2, 0, 0, &needed); + QScopedArrayPointer buffer(new BYTE[needed]); + if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { + PPRINTER_INFO_2 info = reinterpret_cast(buffer.data()); + m_name = QString::fromWCharArray(info->pPrinterName); + m_location = QString::fromWCharArray(info->pLocation); + m_makeAndModel = QString::fromWCharArray(info->pDriverName); // TODO Check is not available elsewhere + m_isRemote = info->Attributes & PRINTER_ATTRIBUTE_NETWORK; + } + m_supportsMultipleCopies = (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COPIES, NULL, NULL) > 1); + m_supportsCollateCopies = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLLATE, NULL, NULL); + // Min/Max custom size is in tenths of a millimeter + const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter); + DWORD min = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MINEXTENT, NULL, NULL); + m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier); + DWORD max = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MAXEXTENT, NULL, NULL); + m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier); + m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0); + } + } +} + +QWindowsPrintDevice::QWindowsPrintDevice(const QWindowsPrintDevice &other) + : QPlatformPrintDevice(other) +{ + OpenPrinter((LPWSTR)other.m_id.utf16(), &m_hPrinter, NULL); +} + +QWindowsPrintDevice::~QWindowsPrintDevice() +{ + ClosePrinter(m_hPrinter); +} + +QWindowsPrintDevice &QWindowsPrintDevice::operator=(const QWindowsPrintDevice &other) +{ + OpenPrinter((LPWSTR)other.m_id.utf16(), &m_hPrinter, NULL); + return *this; +} + +bool QWindowsPrintDevice::operator==(const QWindowsPrintDevice &other) const +{ + return (m_id == other.m_id); +} + +bool QWindowsPrintDevice::isValid() const +{ + return m_hPrinter; +} + +bool QWindowsPrintDevice::isDefault() const +{ + return m_id == defaultPrintDeviceId(); +} + +QPrint::DeviceState QWindowsPrintDevice::state() const +{ + DWORD needed = 0; + GetPrinter(m_hPrinter, 6, 0, 0, &needed); + QScopedArrayPointer buffer(new BYTE[needed]); + + if (GetPrinter(m_hPrinter, 6, buffer.data(), needed, &needed)) { + PPRINTER_INFO_6 info = reinterpret_cast(buffer.data()); + // TODO Check mapping + if (info->dwStatus == 0 + || (info->dwStatus & PRINTER_STATUS_WAITING) == PRINTER_STATUS_WAITING + || (info->dwStatus & PRINTER_STATUS_POWER_SAVE) == PRINTER_STATUS_POWER_SAVE) { + return QPrint::Idle; + } else if ((info->dwStatus & PRINTER_STATUS_PRINTING) == PRINTER_STATUS_PRINTING + || (info->dwStatus & PRINTER_STATUS_BUSY) == PRINTER_STATUS_BUSY + || (info->dwStatus & PRINTER_STATUS_INITIALIZING) == PRINTER_STATUS_INITIALIZING + || (info->dwStatus & PRINTER_STATUS_IO_ACTIVE) == PRINTER_STATUS_IO_ACTIVE + || (info->dwStatus & PRINTER_STATUS_PROCESSING) == PRINTER_STATUS_PROCESSING + || (info->dwStatus & PRINTER_STATUS_WARMING_UP) == PRINTER_STATUS_WARMING_UP) { + return QPrint::Active; + } + } + + return QPrint::Error; +} + +void QWindowsPrintDevice::loadPageSizes() const +{ + // Get the number of paper sizes and check all 3 attributes have same count + DWORD paperCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERNAMES, NULL, NULL); + if (int(paperCount) > 0 + && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERSIZE, NULL, NULL) == paperCount + && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, NULL, NULL) == paperCount) { + + QScopedArrayPointer paperNames(new wchar_t[paperCount*64]); + QScopedArrayPointer winSizes(new POINT[paperCount*sizeof(POINT)]); + QScopedArrayPointer papers(new wchar_t[paperCount]); + + // Get the details and match the default paper size + if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERNAMES, paperNames.data(), NULL) == paperCount + && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERSIZE, (wchar_t *)winSizes.data(), NULL) == paperCount + && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, papers.data(), NULL) == paperCount) { + + // Returned size is in tenths of a millimeter + const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter); + for (int i = 0; i < int(paperCount); ++i) { + QSize size = QSize(qRound((winSizes[i].x / 10.0) * multiplier), qRound((winSizes[i].y / 10.0) * multiplier)); + wchar_t *paper = paperNames.data() + (i * 64); + QString name = QString::fromWCharArray(paper, qwcsnlen(paper, 64)); + m_pageSizes.append(createPageSize(papers[i], size, name)); + } + + } + } + + m_havePageSizes = true; +} + +QPageSize QWindowsPrintDevice::defaultPageSize() const +{ + if (!m_havePageSizes) + loadPageSizes(); + + QPageSize pageSize; + + // Allocate the required DEVMODE buffer + DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); + LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); + + // Get the default DevMode + DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); + + // Get the default paper size + if (result == IDOK && pDevMode->dmFields & DM_PAPERSIZE) { + // Find the supported page size that matches, in theory default should be one of them + foreach (const QPageSize &ps, m_pageSizes) { + if (ps.windowsId() == pDevMode->dmPaperSize) { + pageSize = ps; + break; + } + } + } + + // Clean-up + free(pDevMode); + return pageSize; +} + +QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + // TODO This is slow, need to cache values or find better way! + // Modify the DevMode to get the DC printable margins in device pixels + QMarginsF margins = QMarginsF(0, 0, 0, 0); + DWORD needed = 0; + GetPrinter(m_hPrinter, 2, 0, 0, &needed); + QScopedArrayPointer buffer(new BYTE[needed]); + if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { + PPRINTER_INFO_2 info = reinterpret_cast(buffer.data()); + DEVMODE *devMode = info->pDevMode; + HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode); + if (pageSize.id() == QPageSize::Custom || pageSize.windowsId() <= 0 || pageSize.windowsId() > DMPAPER_LAST) { + devMode->dmPaperSize = 0; + devMode->dmPaperWidth = pageSize.size(QPageSize::Millimeter).width() * 10.0; + devMode->dmPaperLength = pageSize.size(QPageSize::Millimeter).height() * 10.0; + } else { + devMode->dmPaperSize = pageSize.windowsId(); + } + devMode->dmPrintQuality = resolution; + devMode->dmOrientation = orientation == QPageLayout::Portrait ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE; + ResetDC(pDC, devMode); + const int dpiWidth = GetDeviceCaps(pDC, LOGPIXELSX); + const int dpiHeight = GetDeviceCaps(pDC, LOGPIXELSY); + const qreal wMult = 72.0 / dpiWidth; + const qreal hMult = 72.0 / dpiHeight; + const qreal physicalWidth = GetDeviceCaps(pDC, PHYSICALWIDTH) * wMult; + const qreal physicalHeight = GetDeviceCaps(pDC, PHYSICALHEIGHT) * hMult; + const qreal printableWidth = GetDeviceCaps(pDC, HORZRES) * wMult; + const qreal printableHeight = GetDeviceCaps(pDC, VERTRES) * hMult; + const qreal leftMargin = GetDeviceCaps(pDC, PHYSICALOFFSETX)* wMult; + const qreal topMargin = GetDeviceCaps(pDC, PHYSICALOFFSETY) * hMult; + const qreal rightMargin = physicalWidth - leftMargin - printableWidth; + const qreal bottomMargin = physicalHeight - topMargin - printableHeight; + margins = QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin); + ReleaseDC(NULL, pDC); + } + return margins; +} + +void QWindowsPrintDevice::loadResolutions() const +{ + DWORD resCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, NULL, NULL); + if (int(resCount) > 0) { + QScopedArrayPointer resolutions(new LONG[resCount*sizeof(LONG)]); + // Get the details and match the default paper size + if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, (LPWSTR)resolutions.data(), NULL) == resCount) { + for (int i = 0; i < int(resCount); ++i) + m_resolutions.append(resolutions[i]); + } + } + m_haveResolutions = true; +} + +int QWindowsPrintDevice::defaultResolution() const +{ + int resolution = 72; // TODO Set a sensible default? + + // Allocate the required DEVMODE buffer + DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); + LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); + + // Get the default DevMode + DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); + + // Get the default resolution + if (result == IDOK && pDevMode->dmFields & DM_YRESOLUTION) { + if (pDevMode->dmPrintQuality > 0) + resolution = pDevMode->dmPrintQuality; + else + resolution = pDevMode->dmYResolution; + } + + // Clean-up + free(pDevMode); + return resolution; +} + +void QWindowsPrintDevice::loadInputSlots() const +{ + DWORD binCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINS, NULL, NULL); + if (int(binCount) > 0 + && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINNAMES, NULL, NULL) == binCount) { + + QScopedArrayPointer bins(new WORD[binCount*sizeof(WORD)]); + QScopedArrayPointer binNames(new wchar_t[binCount*24]); + + // Get the details and match the default paper size + if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINS, (LPWSTR)bins.data(), NULL) == binCount + && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINNAMES, binNames.data(), NULL) == binCount) { + + for (int i = 0; i < int(binCount); ++i) { + wchar_t *binName = binNames.data() + (i * 24); + QString name = QString::fromWCharArray(binName, qwcsnlen(binName, 24)); + m_inputSlots.append(paperBinToInputSlot(bins[i], name)); + } + + } + } + + m_haveInputSlots = true; +} + +QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot() const +{ + QPrint::InputSlot inputSlot = QPlatformPrintDevice::defaultInputSlot();; + + // Allocate the required DEVMODE buffer + DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); + LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); + + // Get the default DevMode + DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); + + // Get the default input slot + if (result == IDOK && pDevMode->dmFields & DM_DEFAULTSOURCE) { + QPrint::InputSlot tempSlot = paperBinToInputSlot(pDevMode->dmDefaultSource, QString()); + foreach (const QPrint::InputSlot &slot, supportedInputSlots()) { + if (slot.key == tempSlot.key) { + inputSlot = slot; + break; + } + } + } + + // Clean-up + free(pDevMode); + return inputSlot; +} + +void QWindowsPrintDevice::loadOutputBins() const +{ + m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); + m_haveOutputBins = true; +} + +void QWindowsPrintDevice::loadDuplexModes() const +{ + m_duplexModes.append(QPrint::DuplexNone); + DWORD duplex = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_DUPLEX, NULL, NULL); + if (int(duplex) == 1) { + // TODO Assume if duplex flag supports both modes + m_duplexModes.append(QPrint::DuplexLongSide); + m_duplexModes.append(QPrint::DuplexShortSide); + } + m_haveDuplexModes = true; +} + +QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const +{ + QPrint::DuplexMode duplexMode = QPrint::DuplexNone; + + // Allocate the required DEVMODE buffer + DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); + LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); + + // Get the default DevMode + DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); + + // Get the default duplex mode + if (result == IDOK && pDevMode->dmFields & DM_DUPLEX) { + if (pDevMode->dmDuplex == DMDUP_VERTICAL) + duplexMode = QPrint::DuplexLongSide; + else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL) + duplexMode = QPrint::DuplexShortSide; + } + + // Clean-up + free(pDevMode); + return duplexMode; +} + +void QWindowsPrintDevice::loadColorModes() const +{ + m_colorModes.append(QPrint::GrayScale); + DWORD color = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLORDEVICE, NULL, NULL); + if (int(color) == 1) + m_colorModes.append(QPrint::Color); + m_haveColorModes = true; +} + +QPrint::ColorMode QWindowsPrintDevice::defaultColorMode() const +{ + if (!m_haveColorModes) + loadColorModes(); + if (!m_colorModes.contains(QPrint::Color)) + return QPrint::GrayScale; + + QPrint::ColorMode colorMode = QPrint::GrayScale; + + // Allocate the required DEVMODE buffer + DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0); + LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize); + + // Get the default DevMode + DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER); + + // Get the default color mode + if (result == IDOK && pDevMode->dmFields & DM_COLOR) { + if (pDevMode->dmColor == DMCOLOR_COLOR) + colorMode = QPrint::Color; + } + + // Clean-up + free(pDevMode); + return colorMode; +} + +QStringList QWindowsPrintDevice::availablePrintDeviceIds() +{ + QStringList list; + DWORD needed = 0; + DWORD returned = 0; + if ((!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + || !needed) { + return list; + } + QScopedArrayPointer buffer(new BYTE[needed]); + if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, buffer.data(), needed, &needed, &returned)) + return list; + PPRINTER_INFO_4 infoList = reinterpret_cast(buffer.data()); + for (uint i = 0; i < returned; ++i) + list.append(QString::fromWCharArray(infoList[i].pPrinterName)); + return list; +} + +QString QWindowsPrintDevice::defaultPrintDeviceId() +{ + DWORD size = 0; + GetDefaultPrinter(NULL, &size); + QScopedArrayPointer name(new wchar_t[size]); + GetDefaultPrinter(name.data(), &size); + return QString::fromWCharArray(name.data()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h new file mode 100644 index 0000000000..f619876dcb --- /dev/null +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSPRINTDEVICE_H +#define QWINDOWSPRINTDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include // Some feature dependencies might define QT_NO_PRINTER +#ifndef QT_NO_PRINTER + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QWindowsPrintDevice : public QPlatformPrintDevice +{ +public: + QWindowsPrintDevice(); + explicit QWindowsPrintDevice(const QString &id); + QWindowsPrintDevice(const QWindowsPrintDevice &other); + virtual ~QWindowsPrintDevice(); + + QWindowsPrintDevice &operator=(const QWindowsPrintDevice &other); + + QWindowsPrintDevice *clone(); + + bool operator==(const QWindowsPrintDevice &other) const; + + bool isValid() const Q_DECL_OVERRIDE; + bool isDefault() const Q_DECL_OVERRIDE; + + QPrint::DeviceState state() const Q_DECL_OVERRIDE; + + QPageSize defaultPageSize() const Q_DECL_OVERRIDE; + + QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, + int resolution) const Q_DECL_OVERRIDE; + + int defaultResolution() const Q_DECL_OVERRIDE; + + QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE; + + QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE; + + QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE; + + static QStringList availablePrintDeviceIds(); + static QString defaultPrintDeviceId(); + +protected: + void loadPageSizes() const Q_DECL_OVERRIDE; + void loadResolutions() const Q_DECL_OVERRIDE; + void loadInputSlots() const Q_DECL_OVERRIDE; + void loadOutputBins() const Q_DECL_OVERRIDE; + void loadDuplexModes() const Q_DECL_OVERRIDE; + void loadColorModes() const Q_DECL_OVERRIDE; + +private: + HANDLE m_hPrinter; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER +#endif // QWINDOWSPRINTDEVICE_H diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp index b7ba9ef5e7..2da10fc5d0 100644 --- a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qwindowsprintersupport.h" +#include "qwindowsprintdevice.h" #include #include @@ -47,6 +48,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -71,6 +73,21 @@ QPaintEngine *QWindowsPrinterSupport::createPaintEngine(QPrintEngine *engine, QP return static_cast(engine); } +QPrintDevice QWindowsPrinterSupport::createPrintDevice(const QString &id) +{ + return QPlatformPrinterSupport::createPrintDevice(new QWindowsPrintDevice(id)); +} + +QStringList QWindowsPrinterSupport::availablePrintDeviceIds() const +{ + return QWindowsPrintDevice::availablePrintDeviceIds(); +} + +QString QWindowsPrinterSupport::defaultPrintDeviceId() const +{ + return QWindowsPrintDevice::defaultPrintDeviceId(); +} + QList QWindowsPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const { return QWin32PrintEngine::supportedPaperSizes(printerInfo); diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h index 1b1b1fa215..7b82d214ff 100644 --- a/src/plugins/printsupport/windows/qwindowsprintersupport.h +++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h @@ -56,8 +56,14 @@ public: virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode); + + QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; + QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; + QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; + virtual QList supportedPaperSizes(const QPrinterInfo &) const; virtual QList >supportedSizesWithNames(const QPrinterInfo &printerInfo) const; + virtual QList availablePrinters(); private: diff --git a/src/plugins/printsupport/windows/windows.pro b/src/plugins/printsupport/windows/windows.pro index ae9efa342b..364e19e68e 100644 --- a/src/plugins/printsupport/windows/windows.pro +++ b/src/plugins/printsupport/windows/windows.pro @@ -12,10 +12,12 @@ INCLUDEPATH *= $$QT_SOURCE_TREE/src/printsupport/kernel SOURCES += \ main.cpp \ - qwindowsprintersupport.cpp + qwindowsprintersupport.cpp \ + qwindowsprintdevice.cpp \ HEADERS += \ - qwindowsprintersupport.h + qwindowsprintersupport.h \ + qwindowsprintdevice.h \ OTHER_FILES += windows.json -- cgit v1.2.3 From b0428926cece7bc362bc24c2eb1621b9fef737c7 Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 18 Dec 2013 21:51:12 +0100 Subject: QPrinterInfo - Switch to QPlatformPrintDevice Change the QPrinterInfo implementation to use QPlatformPrintDevice as the backend. Remove all the old QPrinterInfo related code from the QPA plugin. Add public api to QPrinterInfo to support some features from QPlatformPrintDevice. [ChangeLog][QtPrintSupport][QPrinterInfo] Added new public api for isRemote(), state(), defaultPageSize(), supportedPageSizes(), supportsCustomPageSizes(), minimumPhysicalPageSize(), maximumPhysicalPageSize(), supportedResolutions(), availablePrinterNames(), and defaultPrinterName(). The use of availablePrinters() is discouraged due to performance concerns. Task-number: QTBUG-35248 Change-Id: Ic38323a930549ad67bf04a1a6bb43d623dfe6a33 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qcocoaprintersupport.h | 8 - .../platforms/cocoa/qcocoaprintersupport.mm | 107 +-------- src/plugins/platforms/cocoa/qprintengine_mac.mm | 5 +- .../printsupport/cups/qcupsprintersupport.cpp | 90 +------- .../printsupport/cups/qcupsprintersupport_p.h | 31 +-- .../windows/qwindowsprintersupport.cpp | 46 +--- .../printsupport/windows/qwindowsprintersupport.h | 14 +- .../kernel/qplatformprintersupport.cpp | 89 +------ src/printsupport/kernel/qplatformprintersupport.h | 20 +- src/printsupport/kernel/qprintengine_win.cpp | 43 ---- src/printsupport/kernel/qprintengine_win_p.h | 8 - src/printsupport/kernel/qprinterinfo.cpp | 255 ++++++++++++++++----- src/printsupport/kernel/qprinterinfo.h | 27 ++- src/printsupport/kernel/qprinterinfo_p.h | 23 +- 14 files changed, 252 insertions(+), 514 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index 4c6a99ec9d..61c1bfd3ec 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -55,18 +55,10 @@ public: QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; - QList supportedPaperSizes(const QPrinterInfo &) const Q_DECL_OVERRIDE; - QList > supportedSizesWithNames(const QPrinterInfo &) const Q_DECL_OVERRIDE; QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; - - QList availablePrinters() Q_DECL_OVERRIDE; - QPrinterInfo printerInfo(const QString &printerName) Q_DECL_OVERRIDE; - -private: - QPrinterInfo printerInfoFromPMPrinter(const PMPrinter &printer); }; #endif // QT_NO_PRINTER diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm index 70c83498e1..5853135dfb 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -42,13 +42,11 @@ #include "qcocoaprintersupport.h" #ifndef QT_NO_PRINTER + #include "qcocoaprintdevice.h" #include "qprintengine_mac_p.h" -#include -#include #include -#include QCocoaPrinterSupport::QCocoaPrinterSupport() { } @@ -104,107 +102,4 @@ QString QCocoaPrinterSupport::defaultPrintDeviceId() const return QString(); } -QList QCocoaPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const -{ - QList returnValue; - if (printerInfo.isNull()) - return returnValue; - - PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName())); - if (!printer) - return returnValue; - - CFArrayRef array; - if (PMPrinterGetPaperList(printer, &array) != noErr) { - PMRelease(printer); - return returnValue; - } - - CFIndex count = CFArrayGetCount(array); - for (CFIndex i = 0; i < count; ++i) { - PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(array, i))); - double width, height; - if (PMPaperGetWidth(paper, &width) == noErr - && PMPaperGetHeight(paper, &height) == noErr) { - // width and height are in points, convertQSizeFToPaperSize() expects millimeters - static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4; - QSizeF size(width * OnePointInMillimeters, height * OnePointInMillimeters); - returnValue += QPlatformPrinterSupport::convertQSizeFToPaperSize(size); - } - } - - PMRelease(printer); - - return returnValue; -} - -QList QCocoaPrinterSupport::availablePrinters() -{ - QList returnValue; - QCFType printerList; - if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { - CFIndex count = CFArrayGetCount(printerList); - for (CFIndex i = 0; i < count; ++i) { - PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); - returnValue += printerInfoFromPMPrinter(printer); - } - } - return returnValue; -} - -QPrinterInfo QCocoaPrinterSupport::printerInfo(const QString &printerName) -{ - PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerName)); - QPrinterInfo pi = printerInfoFromPMPrinter(printer); - PMRelease(printer); - return pi; -} - -QPrinterInfo QCocoaPrinterSupport::printerInfoFromPMPrinter(const PMPrinter &printer) -{ - if (!printer) - return QPrinterInfo(); - - QString name = QCFString::toQString(PMPrinterGetID(printer)); - QString description = QCFString::toQString(PMPrinterGetName(printer)); - QString location = QCFString::toQString(PMPrinterGetLocation(printer)); - CFStringRef cfMakeAndModel; - PMPrinterGetMakeAndModelName(printer, &cfMakeAndModel); - QString makeAndModel = QCFString::toQString(cfMakeAndModel); - bool isDefault = PMPrinterIsDefault(printer); - - return createPrinterInfo(name, description, location, makeAndModel, isDefault, 0); -} - -QList > QCocoaPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const -{ - QList > returnValue; - if (printerInfo.isNull()) - return returnValue; - - PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName())); - if (!printer) - return returnValue; - - CFArrayRef array; - if (PMPrinterGetPaperList(printer, &array) != noErr) { - PMRelease(printer); - return returnValue; - } - - int count = CFArrayGetCount(array); - for (int i = 0; i < count; ++i) { - PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(array, i))); - double width, height; - if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) { - static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4; - QCFString paperName; - if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr) - returnValue.append(qMakePair(QString(paperName), QSizeF(width * OnePointInMillimeters, height * OnePointInMillimeters))); - } - } - PMRelease(printer); - return returnValue; -} - #endif //QT_NO_PRINTER diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 3e92a45a62..f34fadd8a1 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -41,6 +41,7 @@ #include "qprintengine_mac_p.h" #include +#include #include #include @@ -148,7 +149,7 @@ void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps) PMPrinter printer; if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { if (ps != QPrinter::Custom) { - QSizeF newSize = QPlatformPrinterSupport::convertPaperSizeToQSizeF(ps); + QSizeF newSize = QPageSize(QPageSize::PageSizeId(ps)).size(QPageSize::Millimeter); QCFType formats; if (PMSessionCreatePageFormatList(session(), printer, &formats) == noErr) { CFIndex total = CFArrayGetCount(formats); @@ -197,7 +198,7 @@ QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const PMRect paper; PMGetUnadjustedPaperRect(format(), &paper); QSizeF sizef((paper.right - paper.left) / 72.0 * 25.4, (paper.bottom - paper.top) / 72.0 * 25.4); - return QPlatformPrinterSupport::convertQSizeFToPaperSize(sizef); + return QPrinter::PaperSize(QPageSize(sizef, QPageSize::Millimeter).id()); } void QMacPrintEnginePrivate::setPaperName(const QString &name) diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp index 0db448f4bf..b2abb07fc7 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp +++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp @@ -58,18 +58,13 @@ QT_BEGIN_NAMESPACE -QCupsPrinterSupport::QCupsPrinterSupport() : QPlatformPrinterSupport(), - m_cups(QLatin1String("cups"), 2), - m_cupsPrinters(0), - m_cupsPrintersCount(0) +QCupsPrinterSupport::QCupsPrinterSupport() + : QPlatformPrinterSupport() { - loadCups(); - loadCupsPrinters(); } QCupsPrinterSupport::~QCupsPrinterSupport() { - freeCupsPrinters(); } QPrintEngine *QCupsPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode printerMode) @@ -121,87 +116,6 @@ QString QCupsPrinterSupport::defaultPrintDeviceId() const return printerId; } -QList QCupsPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const -{ - return QCUPSSupport::getCupsPrinterPaperSizes(printerIndex(printerInfo)); -} - -QList > QCupsPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const -{ - return QCUPSSupport::getCupsPrinterPaperSizesWithNames(printerIndex(printerInfo)); -} - -void QCupsPrinterSupport::loadCups() -{ - cupsGetDests = (CupsGetDests) m_cups.resolve("cupsGetDests"); - cupsFreeDests = (CupsFreeDests) m_cups.resolve("cupsFreeDests"); - cupsGetOption = (CupsGetOption) m_cups.resolve("cupsGetOption"); -} - -void QCupsPrinterSupport::freeCupsPrinters() -{ - if (cupsFreeDests && m_cupsPrintersCount) { - cupsFreeDests(m_cupsPrintersCount, m_cupsPrinters); - m_cupsPrintersCount = 0; - m_cupsPrinters = 0; - } -} - -void QCupsPrinterSupport::loadCupsPrinters() -{ - freeCupsPrinters(); - m_printers.clear(); - - if (cupsGetDests) - m_cupsPrintersCount = cupsGetDests(&m_cupsPrinters); - - for (int i = 0; i < m_cupsPrintersCount; ++i) { - QString printerName = QString::fromLocal8Bit(m_cupsPrinters[i].name); - if (m_cupsPrinters[i].instance) - printerName += QLatin1Char('/') + QString::fromLocal8Bit(m_cupsPrinters[i].instance); - QString description = cupsOption(i, "printer-info"); - QString location = cupsOption(i, "printer-location"); - QString makeAndModel = cupsOption(i, "printer-make-and-model"); - QPrinterInfo printer = createPrinterInfo(printerName, description, location, makeAndModel, - m_cupsPrinters[i].is_default, i); - m_printers.append(printer); - } -} - -QList QCupsPrinterSupport::availablePrinters() -{ - loadCupsPrinters(); - return QPlatformPrinterSupport::availablePrinters(); -} - -QString QCupsPrinterSupport::printerOption(const QPrinterInfo &printer, const QString &key) const -{ - return cupsOption(printerIndex(printer), key); -} - -QString QCupsPrinterSupport::cupsOption(int i, const QString &key) const -{ - QString value; - if (i > -1 && i < m_cupsPrintersCount && cupsGetOption) - value = cupsGetOption(key.toLocal8Bit(), m_cupsPrinters[i].num_options, m_cupsPrinters[i].options); - return value; -} - -PrinterOptions QCupsPrinterSupport::printerOptions(const QPrinterInfo &printer) const -{ - PrinterOptions options; - int p = printerIndex(printer); - if (p <= -1 || p >= m_cupsPrintersCount) - return options; - int numOptions = m_cupsPrinters[p].num_options; - for (int i = 0; i < numOptions; ++i) { - QString name = m_cupsPrinters[p].options[i].name; - QString value = m_cupsPrinters[p].options[i].value; - options.insert(name, value); - } - return options; -} - QT_END_NAMESPACE #endif // QT_NO_PRINTER diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h index 9ae4a2cd58..27741a52fe 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h +++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h @@ -48,50 +48,25 @@ #include -#include -#include - -#include +#include QT_BEGIN_NAMESPACE -typedef int (*CupsGetDests)(cups_dest_t **dests); -typedef void (*CupsFreeDests)(int num_dests, cups_dest_t *dests); -typedef const char* (*CupsGetOption)(const char *name, int num_options, cups_option_t *options); - class QCupsPrinterSupport : public QPlatformPrinterSupport { public: QCupsPrinterSupport(); ~QCupsPrinterSupport(); - virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); - virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode); + QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; + QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) Q_DECL_OVERRIDE; QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; - virtual QList supportedPaperSizes(const QPrinterInfo &) const; - virtual QList > supportedSizesWithNames(const QPrinterInfo &) const; - - virtual QList availablePrinters(); - virtual QString printerOption(const QPrinterInfo &printer, const QString &key) const; - virtual PrinterOptions printerOptions(const QPrinterInfo &printer) const; - private: - void loadCups(); - void loadCupsPrinters(); - void freeCupsPrinters(); QString cupsOption(int i, const QString &key) const; - - QLibrary m_cups; - cups_dest_t *m_cupsPrinters; - int m_cupsPrintersCount; - - CupsGetDests cupsGetDests; - CupsFreeDests cupsFreeDests; - CupsGetOption cupsGetOption; }; QT_END_NAMESPACE diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp index 2da10fc5d0..997082a367 100644 --- a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp @@ -42,12 +42,8 @@ #include "qwindowsprintersupport.h" #include "qwindowsprintdevice.h" -#include -#include -#include +#include #include -#include -#include #include QT_BEGIN_NAMESPACE @@ -55,7 +51,6 @@ QT_BEGIN_NAMESPACE QWindowsPrinterSupport::QWindowsPrinterSupport() : QPlatformPrinterSupport() { - m_printers = QWindowsPrinterSupport::queryPrinters(); } QWindowsPrinterSupport::~QWindowsPrinterSupport() @@ -88,43 +83,4 @@ QString QWindowsPrinterSupport::defaultPrintDeviceId() const return QWindowsPrintDevice::defaultPrintDeviceId(); } -QList QWindowsPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const -{ - return QWin32PrintEngine::supportedPaperSizes(printerInfo); -} - -QList >QWindowsPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const -{ - return QWin32PrintEngine::supportedSizesWithNames(printerInfo); -} - -QList QWindowsPrinterSupport::availablePrinters() -{ - m_printers = QWindowsPrinterSupport::queryPrinters(); - return QPlatformPrinterSupport::availablePrinters(); -} - -QList QWindowsPrinterSupport::queryPrinters() -{ - QList result; - DWORD needed = 0; - DWORD returned = 0; - if ((!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) - || !needed) { - return result; - } - QScopedArrayPointer buffer(new BYTE[needed]); - if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, buffer.data(), needed, &needed, &returned)) - return result; - PPRINTER_INFO_4 infoList = reinterpret_cast(buffer.data()); - QString defaultPrinterName; - QWin32PrintEngine::queryDefaultPrinter(defaultPrinterName); - for (uint i = 0; i < returned; ++i) { - const QString printerName(QString::fromWCharArray(infoList[i].pPrinterName)); - const bool isDefault = (printerName == defaultPrinterName); - result.append(QPlatformPrinterSupport::createPrinterInfo(printerName, QString(), QString(), QString(), isDefault, i)); - } - return result; -} - QT_END_NAMESPACE diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h index 7b82d214ff..6a84b667dd 100644 --- a/src/plugins/printsupport/windows/qwindowsprintersupport.h +++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h @@ -46,28 +46,18 @@ QT_BEGIN_NAMESPACE -class QWin32PrintEngine; - class QWindowsPrinterSupport : public QPlatformPrinterSupport { public: QWindowsPrinterSupport(); ~QWindowsPrinterSupport(); - virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); - virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode); + QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; + QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) Q_DECL_OVERRIDE; QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; - - virtual QList supportedPaperSizes(const QPrinterInfo &) const; - virtual QList >supportedSizesWithNames(const QPrinterInfo &printerInfo) const; - - virtual QList availablePrinters(); - -private: - static QList queryPrinters(); }; QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qplatformprintersupport.cpp b/src/printsupport/kernel/qplatformprintersupport.cpp index cddf979928..1494155302 100644 --- a/src/printsupport/kernel/qplatformprintersupport.cpp +++ b/src/printsupport/kernel/qplatformprintersupport.cpp @@ -42,6 +42,7 @@ #include "qplatformprintersupport.h" #include "qplatformprintdevice.h" +#include #include #include @@ -105,90 +106,12 @@ QString QPlatformPrinterSupport::defaultPrintDeviceId() const return QString(); } -QList QPlatformPrinterSupport::supportedPaperSizes(const QPrinterInfo &) const +QPageSize QPlatformPrinterSupport::createPageSize(const QString &id, QSize size, const QString &localizedName) { - return QList(); -} - -QList > QPlatformPrinterSupport::supportedSizesWithNames(const QPrinterInfo &) const -{ - return QList >(); -} - -QList QPlatformPrinterSupport::availablePrinters() -{ - return m_printers; -} - -QPrinterInfo QPlatformPrinterSupport::defaultPrinter() -{ - const QList printers = availablePrinters(); - foreach (const QPrinterInfo &printerInfo, printers) { - if (printerInfo.isDefault()) - return printerInfo; - } - return QPrinterInfo(); -} - -QPrinterInfo QPlatformPrinterSupport::printerInfo(const QString &printerName) -{ - const QList printers = availablePrinters(); - foreach (const QPrinterInfo &printerInfo, printers) { - if (printerInfo.printerName() == printerName) - return printerInfo; - } - return QPrinterInfo(); -} - -QString QPlatformPrinterSupport::printerOption(const QPrinterInfo &printer, const QString &key) const -{ - Q_UNUSED(printer) - Q_UNUSED(key) - return QString(); -} - -PrinterOptions QPlatformPrinterSupport::printerOptions(const QPrinterInfo &printer) const -{ - Q_UNUSED(printer) - return PrinterOptions(); -} - -int QPlatformPrinterSupport::printerIndex(const QPrinterInfo &printer) -{ - return printer.d_func()->index; -} - -QPrinterInfo QPlatformPrinterSupport::createPrinterInfo(const QString &name, const QString &description, - const QString &location, const QString &makeAndModel, - bool isDefault, int index) -{ - QPrinterInfo printer(name); - printer.d_func()->description = description; - printer.d_func()->location = location; - printer.d_func()->makeAndModel = makeAndModel; - printer.d_func()->isDefault = isDefault; - printer.d_func()->index = index; - return printer; -} - -/* - Converts QSizeF in millimeters to a predefined PaperSize (returns Custom if - the size isn't a standard size) -*/ -extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF &); -QPrinter::PaperSize QPlatformPrinterSupport::convertQSizeFToPaperSize(const QSizeF &sizef) -{ - return qSizeFTopaperSize(sizef); -} - -/* - Converts a predefined PaperSize to a QSizeF in millimeters (returns - QSizeF(0.0, 0.0) if PaperSize is Custom) -*/ -extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size); -QSizeF QPlatformPrinterSupport::convertPaperSizeToQSizeF(QPrinter::PaperSize paperSize) -{ - return qt_paperSizeToQSizeF(paperSize); + Q_UNUSED(id) + Q_UNUSED(size) + Q_UNUSED(localizedName) + return QPageSize(); } QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qplatformprintersupport.h b/src/printsupport/kernel/qplatformprintersupport.h index 6a4ecc09c8..0efec08f64 100644 --- a/src/printsupport/kernel/qplatformprintersupport.h +++ b/src/printsupport/kernel/qplatformprintersupport.h @@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE typedef QHash PrinterOptions; +class QPageSize; class QPlatformPrintDevice; class QPrintDevice; class QPrintEngine; @@ -80,26 +81,9 @@ public: virtual QStringList availablePrintDeviceIds() const; virtual QString defaultPrintDeviceId() const; - virtual QList supportedPaperSizes(const QPrinterInfo &) const; - virtual QList > supportedSizesWithNames(const QPrinterInfo &printerInfo) const; - virtual QList availablePrinters(); - virtual QPrinterInfo defaultPrinter(); - virtual QPrinterInfo printerInfo(const QString &printerName); - - virtual QString printerOption(const QPrinterInfo &printer, const QString &key) const; - virtual PrinterOptions printerOptions(const QPrinterInfo &printer) const; - - static QPrinter::PaperSize convertQSizeFToPaperSize(const QSizeF &sizef); - static QSizeF convertPaperSizeToQSizeF(QPrinter::PaperSize paperSize); - protected: - static int printerIndex(const QPrinterInfo &printer); - static QPrinterInfo createPrinterInfo(const QString &name, const QString &description, - const QString &location, const QString &makeAndModel, - bool isDefault, int index); static QPrintDevice createPrintDevice(QPlatformPrintDevice *device); - - QList m_printers; + static QPageSize createPageSize(const QString &id, QSize size, const QString &localizedName); }; #endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 02b5d824f4..c5f5057b14 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1733,49 +1733,6 @@ void QWin32PrintEngine::releaseDC(HDC) const } -QList QWin32PrintEngine::supportedPaperSizes(const QPrinterInfo &printerInfo) -{ - QList returnList; - - if (printerInfo.isNull()) - return returnList; - const wchar_t *name = reinterpret_cast(printerInfo.printerName().utf16()); - DWORD size = DeviceCapabilities(name, NULL, DC_PAPERS, NULL, NULL); - if ((int)size != -1) { - QScopedArrayPointer papers(new wchar_t[size]); - if (size != DeviceCapabilities(name, NULL, DC_PAPERS, papers.data(), NULL)) - return returnList; - for (int c = 0; c < (int)size; ++c) - returnList.append(mapDevmodePaperSize(papers[c])); - } - return returnList; -} - -QList > QWin32PrintEngine::supportedSizesWithNames(const QPrinterInfo &printerInfo) -{ - QList > paperSizes; - if (printerInfo.isNull()) - return paperSizes; - const wchar_t *name = reinterpret_cast(printerInfo.printerName().utf16()); - DWORD size = DeviceCapabilities(name, NULL, DC_PAPERNAMES, NULL, NULL); - if ((int)size > 0) { - QScopedArrayPointer papers(new wchar_t[size*64]); - if (size != DeviceCapabilities(name, NULL, DC_PAPERNAMES, papers.data(), NULL)) - return paperSizes; - if (size != DeviceCapabilities(name, NULL, DC_PAPERSIZE, NULL, NULL)) - return paperSizes; - QScopedArrayPointer points(new POINT[size*sizeof(POINT)]); - if (size != DeviceCapabilities(name, NULL, DC_PAPERSIZE, (wchar_t *)points.data(), NULL)) - return paperSizes; - for (int i = 0; i < (int)size; ++i) { - wchar_t *paper = papers.data() + (i * 64); - QString str = QString::fromWCharArray(paper, qwcsnlen(paper, 64)); - paperSizes << qMakePair(str, QSizeF(points[i].x / 10.0, points[i].y / 10.0)); - } - } - return paperSizes; -} - void QWin32PrintEngine::queryDefaultPrinter(QString &name) { /* Read the default printer name, driver and port with the intuitive function diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index d720561c2a..a749d9be42 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -105,14 +105,6 @@ public: HDC getDC() const; void releaseDC(HDC) const; - static QList supportedPaperSizes(const QPrinterInfo &printerInfo); - static QList > supportedSizesWithNames(const QPrinterInfo &printerInfo); - - /* Used by print/page setup dialogs */ - void setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode); - HGLOBAL *createGlobalDevNames(); - HGLOBAL globalDevMode(); - static void queryDefaultPrinter(QString &name); private: diff --git a/src/printsupport/kernel/qprinterinfo.cpp b/src/printsupport/kernel/qprinterinfo.cpp index e02617fe93..b1321bf57a 100644 --- a/src/printsupport/kernel/qprinterinfo.cpp +++ b/src/printsupport/kernel/qprinterinfo.cpp @@ -27,6 +27,7 @@ #include "qprinterinfo.h" #include "qprinterinfo_p.h" +#include "qprintdevice_p.h" #ifndef QT_NO_PRINTER @@ -47,6 +48,19 @@ public: } }; +QPrinterInfoPrivate::QPrinterInfoPrivate(const QString &id) +{ + if (!id.isEmpty()) { + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) + m_printDevice = ps->createPrintDevice(id); + } +} + +QPrinterInfoPrivate::~QPrinterInfoPrivate() +{ +} + /*! \class QPrinterInfo @@ -64,28 +78,6 @@ public: \since 4.4 */ -/*! - \fn QList QPrinterInfo::availablePrinters() - - Returns a list of available printers on the system. -*/ - -/*! - \fn QPrinterInfo QPrinterInfo::defaultPrinter() - - Returns the default printer on the system. - - The return value should be checked using isNull() before being - used, in case there is no default printer. - - On some systems it is possible for there to be available printers - but none of them set to be the default printer. - - \sa isNull() - \sa isDefault() - \sa availablePrinters() -*/ - /*! Constructs an empty QPrinterInfo object. @@ -112,7 +104,7 @@ QPrinterInfo::QPrinterInfo(const QPrinter &printer) { QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); if (ps) { - QPrinterInfo pi = ps->printerInfo(printer.printerName()); + QPrinterInfo pi(printer.printerName()); if (pi.d_ptr.data() == shared_null) d_ptr.reset(shared_null); else @@ -160,7 +152,7 @@ QPrinterInfo &QPrinterInfo::operator=(const QPrinterInfo &other) QString QPrinterInfo::printerName() const { const Q_D(QPrinterInfo); - return d->name; + return d->m_printDevice.id(); } /*! @@ -172,7 +164,7 @@ QString QPrinterInfo::printerName() const QString QPrinterInfo::description() const { const Q_D(QPrinterInfo); - return d->description; + return d->m_printDevice.name(); } /*! @@ -183,7 +175,7 @@ QString QPrinterInfo::description() const QString QPrinterInfo::location() const { const Q_D(QPrinterInfo); - return d->location; + return d->m_printDevice.location(); } /*! @@ -194,7 +186,7 @@ QString QPrinterInfo::location() const QString QPrinterInfo::makeAndModel() const { const Q_D(QPrinterInfo); - return d->makeAndModel; + return d->m_printDevice.makeAndModel(); } /*! @@ -206,23 +198,114 @@ QString QPrinterInfo::makeAndModel() const bool QPrinterInfo::isNull() const { Q_D(const QPrinterInfo); - return d == shared_null || d->name.isEmpty(); + return d == shared_null || !d->m_printDevice.isValid(); } /*! - Returns whether this printer is the default printer. + Returns whether this printer is currently the default printer. */ bool QPrinterInfo::isDefault() const { Q_D(const QPrinterInfo); - return d->isDefault; + return d->m_printDevice.isDefault(); +} + +/*! + Returns whether this printer is a remote network printer. + + \since 5.3 +*/ +bool QPrinterInfo::isRemote() const +{ + Q_D(const QPrinterInfo); + return d->m_printDevice.isRemote(); +} + +/*! + Returns the current state of this printer. + + This state may not always be accurate, depending on the platform, printer + driver, or printer itself. + + \since 5.3 +*/ +QPrinter::PrinterState QPrinterInfo::state() const +{ + Q_D(const QPrinterInfo); + return QPrinter::PrinterState(d->m_printDevice.state()); +} + +/*! + Returns a list of Page Sizes supported by this printer. + + \since 5.3 +*/ + +QList QPrinterInfo::supportedPageSizes() const +{ + Q_D(const QPrinterInfo); + return d->m_printDevice.supportedPageSizes(); +} + +/*! + Returns the current default Page Size for this printer. + + \since 5.3 +*/ + +QPageSize QPrinterInfo::defaultPageSize() const +{ + Q_D(const QPrinterInfo); + return d->m_printDevice.defaultPageSize(); +} + +/*! + Returns whether this printer supports custom page sizes. + + \since 5.3 +*/ + +bool QPrinterInfo::supportsCustomPageSizes() const +{ + Q_D(const QPrinterInfo); + return d->m_printDevice.supportsCustomPageSizes(); } /*! + Returns the minimum physical page size supported by this printer. + + \sa maximumPhysicalPageSize() + + \since 5.3 +*/ + +QPageSize QPrinterInfo::minimumPhysicalPageSize() const +{ + Q_D(const QPrinterInfo); + return QPageSize(d->m_printDevice.minimumPhysicalPageSize(), QString(), QPageSize::ExactMatch); +} + +/*! + Returns the maximum physical page size supported by this printer. + + \sa minimumPhysicalPageSize() + + \since 5.3 +*/ + +QPageSize QPrinterInfo::maximumPhysicalPageSize() const +{ + Q_D(const QPrinterInfo); + return QPageSize(d->m_printDevice.maximumPhysicalPageSize(), QString(), QPageSize::ExactMatch); +} + +#if QT_DEPRECATED_SINCE(5,3) +/*! + \obsolete Use supportedPageSizes() instead. + Returns a list of supported paper sizes by the printer. Not all printer drivers support this query, so the list may be empty. - On Mac OS X 10.3, this function always returns an empty list. \since 4.4 */ @@ -230,14 +313,15 @@ bool QPrinterInfo::isDefault() const QList QPrinterInfo::supportedPaperSizes() const { Q_D(const QPrinterInfo); - if (!isNull() && !d->hasPaperSizes) { - d->paperSizes = QPlatformPrinterSupportPlugin::get()->supportedPaperSizes(*this); - d->hasPaperSizes = true; - } - return d->paperSizes; + QList list; + foreach (const QPageSize &pageSize, d->m_printDevice.supportedPageSizes()) + list.append(QPrinter::PaperSize(pageSize.id())); + return list; } /*! + \obsolete Use supportedPageSizes() instead. + Returns a list of all the paper names supported by the driver with the corresponding size in millimeters. @@ -249,27 +333,99 @@ QList QPrinterInfo::supportedPaperSizes() const QList > QPrinterInfo::supportedSizesWithNames() const { Q_D(const QPrinterInfo); - if (!isNull() && !d->hasPaperNames) { - d->paperNames = QPlatformPrinterSupportPlugin::get()->supportedSizesWithNames(*this); - d->hasPaperNames = true; - } - return d->paperNames; + QList > list; + foreach (const QPageSize &pageSize, d->m_printDevice.supportedPageSizes()) + list.append(qMakePair(pageSize.name(), pageSize.size(QPageSize::Millimeter))); + return list; +} +#endif // QT_DEPRECATED_SINCE(5,3) + +/*! + Returns a list of resolutions supported by this printer. + + \since 5.3 +*/ + +QList QPrinterInfo::supportedResolutions() const +{ + Q_D(const QPrinterInfo); + return d->m_printDevice.supportedResolutions(); } +/*! + Returns a list of all the available Printer Names on this system. + + It is recommended to use this instead of availablePrinters() as + it will be faster on most systems. + + Note that the list may become outdated if changes are made on the local + system or remote print server. Only instantiate required QPrinterInfo + instances when needed, and always check for validity before calling. + + \since 5.3 +*/ +QStringList QPrinterInfo::availablePrinterNames() +{ + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) + return ps->availablePrintDeviceIds(); + return QStringList(); +} + +/*! + Returns a list of QPrinterInfo objects for all the available printers + on this system. + + It is NOT recommended to use this as creating each printer instance may + take a long time, especially if there are remote networked printers, and + retained instances may become outdated if changes are made on the local + system or remote print server. Use availablePrinterNames() instead and + only instantiate printer instances as you need them. +*/ QList QPrinterInfo::availablePrinters() +{ + QList list; + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) { + foreach (const QString &id, ps->availablePrintDeviceIds()) + list.append(QPrinterInfo(id)); + } + return list; +} + +/*! + Returns the current default printer name. + + \since 5.3 +*/ +QString QPrinterInfo::defaultPrinterName() { QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); - if (!ps) - return QList(); - return ps->availablePrinters(); + if (ps) + return ps->defaultPrintDeviceId(); + return QString(); } +/*! + Returns the default printer on the system. + + The return value should be checked using isNull() before being + used, in case there is no default printer. + + On some systems it is possible for there to be available printers + but none of them set to be the default printer. + + \sa isNull() + \sa isDefault() + \sa availablePrinters() +*/ + QPrinterInfo QPrinterInfo::defaultPrinter() { QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); - if (!ps) - return QPrinterInfo(); - return ps->defaultPrinter(); + if (ps) + return QPrinterInfo(ps->defaultPrintDeviceId()); + return QPrinterInfo(); } /*! @@ -283,10 +439,7 @@ QPrinterInfo QPrinterInfo::defaultPrinter() */ QPrinterInfo QPrinterInfo::printerInfo(const QString &printerName) { - QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); - if (!ps) - return QPrinterInfo(); - return ps->printerInfo(printerName); + return QPrinterInfo(printerName); } QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qprinterinfo.h b/src/printsupport/kernel/qprinterinfo.h index 0dc19c1da7..73ec48dfe7 100644 --- a/src/printsupport/kernel/qprinterinfo.h +++ b/src/printsupport/kernel/qprinterinfo.h @@ -42,9 +42,11 @@ #ifndef QPRINTERINFO_H #define QPRINTERINFO_H +#include + #include #include -#include +#include QT_BEGIN_NAMESPACE @@ -69,12 +71,31 @@ public: bool isNull() const; bool isDefault() const; + bool isRemote() const; + + QPrinter::PrinterState state() const; + + QList supportedPageSizes() const; + QPageSize defaultPageSize() const; + + bool supportsCustomPageSizes() const; - QList supportedPaperSizes() const; - QList > supportedSizesWithNames() const; + QPageSize minimumPhysicalPageSize() const; + QPageSize maximumPhysicalPageSize() const; +#if QT_DEPRECATED_SINCE(5,3) + QT_DEPRECATED QList supportedPaperSizes() const; + QT_DEPRECATED QList > supportedSizesWithNames() const; +#endif // QT_DEPRECATED_SINCE(5,3) + + QList supportedResolutions() const; + + static QStringList availablePrinterNames(); static QList availablePrinters(); + + static QString defaultPrinterName(); static QPrinterInfo defaultPrinter(); + static QPrinterInfo printerInfo(const QString &printerName); private: diff --git a/src/printsupport/kernel/qprinterinfo_p.h b/src/printsupport/kernel/qprinterinfo_p.h index 6ae64b5653..7083356e1c 100644 --- a/src/printsupport/kernel/qprinterinfo_p.h +++ b/src/printsupport/kernel/qprinterinfo_p.h @@ -57,32 +57,17 @@ #ifndef QT_NO_PRINTER -#include "QtCore/qlist.h" -#include "QtCore/qpair.h" +#include "qprintdevice_p.h" QT_BEGIN_NAMESPACE class QPrinterInfoPrivate { public: - QPrinterInfoPrivate(const QString& name = QString()) : - name(name), isDefault(false), index(-1), hasPaperSizes(false), - hasPaperNames(false) - {} - ~QPrinterInfoPrivate() - {} + QPrinterInfoPrivate(const QString& id = QString()); + ~QPrinterInfoPrivate(); - QString name; - QString description; - QString location; - QString makeAndModel; - bool isDefault; - int index; // Internal printer plugin use only - - mutable bool hasPaperSizes; - mutable QList paperSizes; - mutable bool hasPaperNames; - mutable QList > paperNames; + QPrintDevice m_printDevice; }; QT_END_NAMESPACE -- cgit v1.2.3 From 4ab55a01e96b6ac398d3a9afa2c93032e305f30b Mon Sep 17 00:00:00 2001 From: John Layt Date: Thu, 26 Dec 2013 11:14:53 +0100 Subject: QPagedPaintDevice - Use QPageSize and QPageLayout Use new QPageLayout and QPageSize class to store and convert page sizes and layouts consistently. Extend the PageSize enum to match QPage::PageSize. Note that public setters/getters cannot be added as virtuals would break BIC, but without virtuals the derived classes would break. Instead an internal api is provided and the derived classes will need to implement identical api to manipulate it. [ChangeLog][QtGui][QPagedPaintDevice] Paged paint devices such as QPrinter and QPdfWriter now support all Postscript standard page sizes. Task-number: QTBUG-27685 Task-number: QTBUG-25744 Change-Id: I62e96ab94194ab4ac8bed8fa804e0ce1c3233313 Reviewed-by: Lars Knoll --- src/gui/painting/qpagedpaintdevice.cpp | 273 ++++++++++++++++++++++----------- src/gui/painting/qpagedpaintdevice.h | 159 ++++++++++++++++++- src/gui/painting/qpagedpaintdevice_p.h | 10 +- src/printsupport/kernel/qprinter.cpp | 196 +++++++++++++++++------ src/printsupport/kernel/qprinter.h | 155 ++++++++++++++++++- 5 files changed, 640 insertions(+), 153 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp index b95b3e3503..18ba964a26 100644 --- a/src/gui/painting/qpagedpaintdevice.cpp +++ b/src/gui/painting/qpagedpaintdevice.cpp @@ -44,42 +44,6 @@ QT_BEGIN_NAMESPACE -static const struct { - float width; - float height; -} pageSizes[] = { - {210, 297}, // A4 - {176, 250}, // B5 - {215.9f, 279.4f}, // Letter - {215.9f, 355.6f}, // Legal - {190.5f, 254}, // Executive - {841, 1189}, // A0 - {594, 841}, // A1 - {420, 594}, // A2 - {297, 420}, // A3 - {148, 210}, // A5 - {105, 148}, // A6 - {74, 105}, // A7 - {52, 74}, // A8 - {37, 52}, // A8 - {1000, 1414}, // B0 - {707, 1000}, // B1 - {31, 44}, // B10 - {500, 707}, // B2 - {353, 500}, // B3 - {250, 353}, // B4 - {125, 176}, // B6 - {88, 125}, // B7 - {62, 88}, // B8 - {44, 62}, // B9 - {163, 229}, // C5E - {105, 241}, // US Common - {110, 220}, // DLE - {210, 330}, // Folio - {431.8f, 279.4f}, // Ledger - {279.4f, 431.8f} // Tabloid -}; - /*! \class QPagedPaintDevice \inmodule QtGui @@ -110,46 +74,147 @@ QPagedPaintDevice::~QPagedPaintDevice() } /*! - \enum QPagedPaintDevice::PageSize - - This enum type specifies the page size of the paint device. - - \value A0 841 x 1189 mm - \value A1 594 x 841 mm - \value A2 420 x 594 mm - \value A3 297 x 420 mm - \value A4 210 x 297 mm, 8.26 x 11.69 inches - \value A5 148 x 210 mm - \value A6 105 x 148 mm - \value A7 74 x 105 mm - \value A8 52 x 74 mm - \value A9 37 x 52 mm - \value B0 1000 x 1414 mm - \value B1 707 x 1000 mm - \value B2 500 x 707 mm - \value B3 353 x 500 mm - \value B4 250 x 353 mm - \value B5 176 x 250 mm, 6.93 x 9.84 inches - \value B6 125 x 176 mm - \value B7 88 x 125 mm - \value B8 62 x 88 mm - \value B9 44 x 62 mm - \value B10 31 x 44 mm - \value C5E 163 x 229 mm - \value Comm10E 105 x 241 mm, U.S. Common 10 Envelope - \value DLE 110 x 220 mm - \value Executive 7.5 x 10 inches, 190.5 x 254 mm - \value Folio 210 x 330 mm - \value Ledger 431.8 x 279.4 mm - \value Legal 8.5 x 14 inches, 215.9 x 355.6 mm - \value Letter 8.5 x 11 inches, 215.9 x 279.4 mm - \value Tabloid 279.4 x 431.8 mm - \value Custom Unknown, or a user defined size. - - \omitvalue NPageSize - - The page size can also be specified in millimeters using setPageSizeMM(). In this case the - page size enum is set to Custom. + \enum QPagedPaintDevice::PageSize + + This enum type lists the available page sizes as defined in the Postscript + PPD standard. These values are duplicated in QPageSize and QPrinter. + + The defined sizes are: + + \value A0 841 x 1189 mm + \value A1 594 x 841 mm + \value A2 420 x 594 mm + \value A3 297 x 420 mm + \value A4 210 x 297 mm, 8.26 x 11.69 inches + \value A5 148 x 210 mm + \value A6 105 x 148 mm + \value A7 74 x 105 mm + \value A8 52 x 74 mm + \value A9 37 x 52 mm + \value B0 1000 x 1414 mm + \value B1 707 x 1000 mm + \value B2 500 x 707 mm + \value B3 353 x 500 mm + \value B4 250 x 353 mm + \value B5 176 x 250 mm, 6.93 x 9.84 inches + \value B6 125 x 176 mm + \value B7 88 x 125 mm + \value B8 62 x 88 mm + \value B9 33 x 62 mm + \value B10 31 x 44 mm + \value C5E 163 x 229 mm + \value Comm10E 105 x 241 mm, U.S. Common 10 Envelope + \value DLE 110 x 220 mm + \value Executive 7.5 x 10 inches, 190.5 x 254 mm + \value Folio 210 x 330 mm + \value Ledger 431.8 x 279.4 mm + \value Legal 8.5 x 14 inches, 215.9 x 355.6 mm + \value Letter 8.5 x 11 inches, 215.9 x 279.4 mm + \value Tabloid 279.4 x 431.8 mm + \value Custom Unknown, or a user defined size. + \value A10 + \value A3Extra + \value A4Extra + \value A4Plus + \value A4Small + \value A5Extra + \value B5Extra + \value JisB0 + \value JisB1 + \value JisB2 + \value JisB3 + \value JisB4 + \value JisB5 + \value JisB6, + \value JisB7 + \value JisB8 + \value JisB9 + \value JisB10 + \value AnsiA = Letter + \value AnsiB = Ledger + \value AnsiC + \value AnsiD + \value AnsiE + \value LegalExtra + \value LetterExtra + \value LetterPlus + \value LetterSmall + \value TabloidExtra + \value ArchA + \value ArchB + \value ArchC + \value ArchD + \value ArchE + \value Imperial7x9 + \value Imperial8x10 + \value Imperial9x11 + \value Imperial9x12 + \value Imperial10x11 + \value Imperial10x13 + \value Imperial10x14 + \value Imperial12x11 + \value Imperial15x11 + \value ExecutiveStandard + \value Note + \value Quarto + \value Statement + \value SuperA + \value SuperB + \value Postcard + \value DoublePostcard + \value Prc16K + \value Prc32K + \value Prc32KBig + \value FanFoldUS + \value FanFoldGerman + \value FanFoldGermanLegal + \value EnvelopeB4 + \value EnvelopeB5 + \value EnvelopeB6 + \value EnvelopeC0 + \value EnvelopeC1 + \value EnvelopeC2 + \value EnvelopeC3 + \value EnvelopeC4 + \value EnvelopeC5 = C5E + \value EnvelopeC6 + \value EnvelopeC65 + \value EnvelopeC7 + \value EnvelopeDL = DLE + \value Envelope9 + \value Envelope10 = Comm10E + \value Envelope11 + \value Envelope12 + \value Envelope14 + \value EnvelopeMonarch + \value EnvelopePersonal + \value EnvelopeChou3 + \value EnvelopeChou4 + \value EnvelopeInvite + \value EnvelopeItalian + \value EnvelopeKaku2 + \value EnvelopeKaku3 + \value EnvelopePrc1 + \value EnvelopePrc2 + \value EnvelopePrc3 + \value EnvelopePrc4 + \value EnvelopePrc5 + \value EnvelopePrc6 + \value EnvelopePrc7 + \value EnvelopePrc8 + \value EnvelopePrc9 + \value EnvelopePrc10 + \value EnvelopeYou4 + \value LastPageSize = EnvelopeYou4 + \omitvalue NPageSize + \omitvalue NPaperSize + + Due to historic reasons QPageSize::Executive is not the same as the standard + Postscript and Windows Executive size, use QPageSize::ExecutiveStandard instead. + + The Postscript standard size QPageSize::Folio is different to the Windows + DMPAPER_FOLIO size, use the Postscript standard size QPageSize::FanFoldGermanLegal + if needed. */ /*! @@ -166,10 +231,7 @@ QPagedPaintDevice::~QPagedPaintDevice() */ void QPagedPaintDevice::setPageSize(PageSize size) { - if (size >= Custom) - return; - d->pageSize = size; - d->pageSizeMM = QSizeF(pageSizes[size].width, pageSizes[size].height); + d->m_pageLayout.setPageSize(QPageSize(QPageSize::PageSizeId(size))); } /*! @@ -177,16 +239,18 @@ void QPagedPaintDevice::setPageSize(PageSize size) */ QPagedPaintDevice::PageSize QPagedPaintDevice::pageSize() const { - return d->pageSize; + return PageSize(d->m_pageLayout.pageSize().id()); } /*! - Sets the page size to \a size. \a size is specified in millimeters. - */ + Sets the page size to \a size. \a size is specified in millimeters. + + If the size matches a standard QPagedPaintDevice::PageSize then that page + size will be used, otherwise QPagedPaintDevice::Custom will be set. +*/ void QPagedPaintDevice::setPageSizeMM(const QSizeF &size) { - d->pageSize = Custom; - d->pageSizeMM = size; + d->m_pageLayout.setPageSize(QPageSize(size, QPageSize::Millimeter)); } /*! @@ -194,7 +258,7 @@ void QPagedPaintDevice::setPageSizeMM(const QSizeF &size) */ QSizeF QPagedPaintDevice::pageSizeMM() const { - return d->pageSizeMM; + return d->m_pageLayout.pageSize().size(QPageSize::Millimeter); } /*! @@ -209,17 +273,48 @@ QSizeF QPagedPaintDevice::pageSizeMM() const */ void QPagedPaintDevice::setMargins(const Margins &margins) { - d->margins = margins; + d->m_pageLayout.setUnits(QPageLayout::Millimeter); + d->m_pageLayout.setMargins(QMarginsF(margins.left, margins.top, margins.right, margins.bottom)); } /*! - returns the current margins of the paint device. The default is 0. + Returns the current margins of the paint device. The default is 0. + + Margins are specified in millimeters. \sa setMargins() */ QPagedPaintDevice::Margins QPagedPaintDevice::margins() const { - return d->margins; + QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Millimeter); + Margins result; + result.left = margins.left(); + result.top = margins.top(); + result.right = margins.right(); + result.bottom = margins.bottom(); + return result; +} + +/*! + \internal + + Returns the internal device page layout. +*/ + +QPageLayout QPagedPaintDevice::devicePageLayout() const +{ + return d->m_pageLayout; +} + +/*! + \internal + + Returns the internal device page layout. +*/ + +QPageLayout &QPagedPaintDevice::devicePageLayout() +{ + return d->m_pageLayout; } QT_END_NAMESPACE diff --git a/src/gui/painting/qpagedpaintdevice.h b/src/gui/painting/qpagedpaintdevice.h index a4e8ff1a48..6d4c422a95 100644 --- a/src/gui/painting/qpagedpaintdevice.h +++ b/src/gui/painting/qpagedpaintdevice.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE #endif class QPagedPaintDevicePrivate; +class QPageLayout; class Q_GUI_EXPORT QPagedPaintDevice : public QPaintDevice { @@ -61,10 +62,157 @@ public: virtual bool newPage() = 0; // ### Qt6 Remove in favor of QPage::PageSize - enum PageSize { A4, B5, Letter, Legal, Executive, - A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1, - B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E, - DLE, Folio, Ledger, Tabloid, Custom, NPageSize = Custom }; + // NOTE: Must keep in sync with QPageSize and QPrinter + enum PageSize { + // Existing Qt sizes + A4, + B5, + Letter, + Legal, + Executive, + A0, + A1, + A2, + A3, + A5, + A6, + A7, + A8, + A9, + B0, + B1, + B10, + B2, + B3, + B4, + B6, + B7, + B8, + B9, + C5E, + Comm10E, + DLE, + Folio, + Ledger, + Tabloid, + Custom, + + // New values derived from PPD standard + A10, + A3Extra, + A4Extra, + A4Plus, + A4Small, + A5Extra, + B5Extra, + + JisB0, + JisB1, + JisB2, + JisB3, + JisB4, + JisB5, + JisB6, + JisB7, + JisB8, + JisB9, + JisB10, + + // AnsiA = Letter, + // AnsiB = Ledger, + AnsiC, + AnsiD, + AnsiE, + LegalExtra, + LetterExtra, + LetterPlus, + LetterSmall, + TabloidExtra, + + ArchA, + ArchB, + ArchC, + ArchD, + ArchE, + + Imperial7x9, + Imperial8x10, + Imperial9x11, + Imperial9x12, + Imperial10x11, + Imperial10x13, + Imperial10x14, + Imperial12x11, + Imperial15x11, + + ExecutiveStandard, + Note, + Quarto, + Statement, + SuperA, + SuperB, + Postcard, + DoublePostcard, + Prc16K, + Prc32K, + Prc32KBig, + + FanFoldUS, + FanFoldGerman, + FanFoldGermanLegal, + + EnvelopeB4, + EnvelopeB5, + EnvelopeB6, + EnvelopeC0, + EnvelopeC1, + EnvelopeC2, + EnvelopeC3, + EnvelopeC4, + // EnvelopeC5 = C5E, + EnvelopeC6, + EnvelopeC65, + EnvelopeC7, + // EnvelopeDL = DLE, + + Envelope9, + // Envelope10 = Comm10E, + Envelope11, + Envelope12, + Envelope14, + EnvelopeMonarch, + EnvelopePersonal, + + EnvelopeChou3, + EnvelopeChou4, + EnvelopeInvite, + EnvelopeItalian, + EnvelopeKaku2, + EnvelopeKaku3, + EnvelopePrc1, + EnvelopePrc2, + EnvelopePrc3, + EnvelopePrc4, + EnvelopePrc5, + EnvelopePrc6, + EnvelopePrc7, + EnvelopePrc8, + EnvelopePrc9, + EnvelopePrc10, + EnvelopeYou4, + + // Last item, with commonly used synynoms from QPagedPrintEngine / QPrinter + LastPageSize = EnvelopeYou4, + NPageSize = LastPageSize, + NPaperSize = LastPageSize, + + // Convenience overloads for naming consistency + AnsiA = Letter, + AnsiB = Ledger, + EnvelopeC5 = C5E, + EnvelopeDL = DLE, + Envelope10 = Comm10E + }; virtual void setPageSize(PageSize size); PageSize pageSize() const; @@ -72,6 +220,7 @@ public: virtual void setPageSizeMM(const QSizeF &size); QSizeF pageSizeMM() const; + // ### Qt6 Remove in favor of QMarginsF struct Margins { qreal left; qreal right; @@ -83,6 +232,8 @@ public: Margins margins() const; protected: + QPageLayout devicePageLayout() const; + QPageLayout &devicePageLayout(); friend class QPagedPaintDevicePrivate; QPagedPaintDevicePrivate *d; }; diff --git a/src/gui/painting/qpagedpaintdevice_p.h b/src/gui/painting/qpagedpaintdevice_p.h index d9e5d43903..da58951dc7 100644 --- a/src/gui/painting/qpagedpaintdevice_p.h +++ b/src/gui/painting/qpagedpaintdevice_p.h @@ -55,27 +55,25 @@ #include +#include "qpagelayout.h" + QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QPagedPaintDevicePrivate { public: QPagedPaintDevicePrivate() - : pageSize(QPagedPaintDevice::A4), - pageSizeMM(210, 297), + : m_pageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0)), fromPage(0), toPage(0), pageOrderAscending(true), printSelectionOnly(false) { - margins.left = margins.right = margins.top = margins.bottom = 0; } static inline QPagedPaintDevicePrivate *get(QPagedPaintDevice *pd) { return pd->d; } - QPagedPaintDevice::PageSize pageSize; - QSizeF pageSizeMM; - QPagedPaintDevice::Margins margins; + QPageLayout m_pageLayout; // These are currently required to keep QPrinter functionality working in QTextDocument::print() int fromPage; diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 9e9a0625d7..878dac60d5 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -418,57 +418,153 @@ void QPrinterPrivate::setProperty(QPrintEngine::PrintEnginePropertyKey key, cons */ /*! - \enum QPrinter::PaperSize - \since 4.4 + \enum QPrinter::PaperSize + \since 4.4 - This enum type specifies what paper size QPrinter should use. - QPrinter does not check that the paper size is available; it just - uses this information, together with QPrinter::Orientation and - QPrinter::setFullPage(), to determine the printable area. - - The defined sizes (with setFullPage(true)) are: - - \value A0 841 x 1189 mm - \value A1 594 x 841 mm - \value A2 420 x 594 mm - \value A3 297 x 420 mm - \value A4 210 x 297 mm, 8.26 x 11.69 inches - \value A5 148 x 210 mm - \value A6 105 x 148 mm - \value A7 74 x 105 mm - \value A8 52 x 74 mm - \value A9 37 x 52 mm - \value B0 1000 x 1414 mm - \value B1 707 x 1000 mm - \value B2 500 x 707 mm - \value B3 353 x 500 mm - \value B4 250 x 353 mm - \value B5 176 x 250 mm, 6.93 x 9.84 inches - \value B6 125 x 176 mm - \value B7 88 x 125 mm - \value B8 62 x 88 mm - \value B9 44 x 62 mm - \value B10 31 x 44 mm - \value C5E 163 x 229 mm - \value Comm10E 105 x 241 mm, U.S. Common 10 Envelope - \value DLE 110 x 220 mm - \value Executive 7.5 x 10 inches, 190.5 x 254 mm - \value Folio 210 x 330 mm - \value Ledger 431.8 x 279.4 mm - \value Legal 8.5 x 14 inches, 215.9 x 355.6 mm - \value Letter 8.5 x 11 inches, 215.9 x 279.4 mm - \value Tabloid 279.4 x 431.8 mm - \value Custom Unknown, or a user defined size. - - With setFullPage(false) (the default), the metrics will be a bit - smaller; how much depends on the printer in use. - - \note QPrinter::Folio is the Adobe specification for the Folio size. - On Windows if you want to use the same as DMPAPER_FOLIO then you should use - setPaperSize(QSizeF(8.5, 13), QPrinter::Inch). - - \omitvalue NPageSize - \omitvalue NPaperSize + This enum type specifies what paper size QPrinter should use. + QPrinter does not check that the paper size is available; it just + uses this information, together with QPrinter::Orientation and + QPrinter::setFullPage(), to determine the printable area. + + The defined sizes (with setFullPage(true)) are: + + \value A0 841 x 1189 mm + \value A1 594 x 841 mm + \value A2 420 x 594 mm + \value A3 297 x 420 mm + \value A4 210 x 297 mm, 8.26 x 11.69 inches + \value A5 148 x 210 mm + \value A6 105 x 148 mm + \value A7 74 x 105 mm + \value A8 52 x 74 mm + \value A9 37 x 52 mm + \value B0 1000 x 1414 mm + \value B1 707 x 1000 mm + \value B2 500 x 707 mm + \value B3 353 x 500 mm + \value B4 250 x 353 mm + \value B5 176 x 250 mm, 6.93 x 9.84 inches + \value B6 125 x 176 mm + \value B7 88 x 125 mm + \value B8 62 x 88 mm + \value B9 33 x 62 mm + \value B10 31 x 44 mm + \value C5E 163 x 229 mm + \value Comm10E 105 x 241 mm, U.S. Common 10 Envelope + \value DLE 110 x 220 mm + \value Executive 7.5 x 10 inches, 190.5 x 254 mm + \value Folio 210 x 330 mm + \value Ledger 431.8 x 279.4 mm + \value Legal 8.5 x 14 inches, 215.9 x 355.6 mm + \value Letter 8.5 x 11 inches, 215.9 x 279.4 mm + \value Tabloid 279.4 x 431.8 mm + \value Custom Unknown, or a user defined size. + \value A10 + \value A3Extra + \value A4Extra + \value A4Plus + \value A4Small + \value A5Extra + \value B5Extra + \value JisB0 + \value JisB1 + \value JisB2 + \value JisB3 + \value JisB4 + \value JisB5 + \value JisB6, + \value JisB7 + \value JisB8 + \value JisB9 + \value JisB10 + \value AnsiA = Letter + \value AnsiB = Ledger + \value AnsiC + \value AnsiD + \value AnsiE + \value LegalExtra + \value LetterExtra + \value LetterPlus + \value LetterSmall + \value TabloidExtra + \value ArchA + \value ArchB + \value ArchC + \value ArchD + \value ArchE + \value Imperial7x9 + \value Imperial8x10 + \value Imperial9x11 + \value Imperial9x12 + \value Imperial10x11 + \value Imperial10x13 + \value Imperial10x14 + \value Imperial12x11 + \value Imperial15x11 + \value ExecutiveStandard + \value Note + \value Quarto + \value Statement + \value SuperA + \value SuperB + \value Postcard + \value DoublePostcard + \value Prc16K + \value Prc32K + \value Prc32KBig + \value FanFoldUS + \value FanFoldGerman + \value FanFoldGermanLegal + \value EnvelopeB4 + \value EnvelopeB5 + \value EnvelopeB6 + \value EnvelopeC0 + \value EnvelopeC1 + \value EnvelopeC2 + \value EnvelopeC3 + \value EnvelopeC4 + \value EnvelopeC5 = C5E + \value EnvelopeC6 + \value EnvelopeC65 + \value EnvelopeC7 + \value EnvelopeDL = DLE + \value Envelope9 + \value Envelope10 = Comm10E + \value Envelope11 + \value Envelope12 + \value Envelope14 + \value EnvelopeMonarch + \value EnvelopePersonal + \value EnvelopeChou3 + \value EnvelopeChou4 + \value EnvelopeInvite + \value EnvelopeItalian + \value EnvelopeKaku2 + \value EnvelopeKaku3 + \value EnvelopePrc1 + \value EnvelopePrc2 + \value EnvelopePrc3 + \value EnvelopePrc4 + \value EnvelopePrc5 + \value EnvelopePrc6 + \value EnvelopePrc7 + \value EnvelopePrc8 + \value EnvelopePrc9 + \value EnvelopePrc10 + \value EnvelopeYou4 + \value LastPageSize = EnvelopeYou4 + \omitvalue NPageSize + \omitvalue NPaperSize + + With setFullPage(false) (the default), the metrics will be a bit + smaller; how much depends on the printer in use. + + Due to historic reasons QPageSize::Executive is not the same as the standard + Postscript and Windows Executive size, use QPageSize::ExecutiveStandard instead. + + The Postscript standard size QPageSize::Folio is different to the Windows + DMPAPER_FOLIO size, use the Postscript standard size QPageSize::FanFoldGermanLegal + if needed. */ diff --git a/src/printsupport/kernel/qprinter.h b/src/printsupport/kernel/qprinter.h index 17afdc2157..f842c222f6 100644 --- a/src/printsupport/kernel/qprinter.h +++ b/src/printsupport/kernel/qprinter.h @@ -76,13 +76,160 @@ public: enum Orientation { Portrait, Landscape }; // ### Qt6 Remove in favor of QPage::PageSize + // NOTE: Must keep in sync with QPageSize and QPagedPaintDevice #ifndef Q_QDOC typedef PageSize PaperSize; #else - enum PaperSize { A4, B5, Letter, Legal, Executive, - A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1, - B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E, - DLE, Folio, Ledger, Tabloid, Custom, NPageSize = Custom, NPaperSize = Custom }; + enum PaperSize { + // Existing Qt sizes + A4, + B5, + Letter, + Legal, + Executive, + A0, + A1, + A2, + A3, + A5, + A6, + A7, + A8, + A9, + B0, + B1, + B10, + B2, + B3, + B4, + B6, + B7, + B8, + B9, + C5E, + Comm10E, + DLE, + Folio, + Ledger, + Tabloid, + Custom, + + // New values derived from PPD standard + A10, + A3Extra, + A4Extra, + A4Plus, + A4Small, + A5Extra, + B5Extra, + + JisB0, + JisB1, + JisB2, + JisB3, + JisB4, + JisB5, + JisB6, + JisB7, + JisB8, + JisB9, + JisB10, + + // AnsiA = Letter, + // AnsiB = Ledger, + AnsiC, + AnsiD, + AnsiE, + LegalExtra, + LetterExtra, + LetterPlus, + LetterSmall, + TabloidExtra, + + ArchA, + ArchB, + ArchC, + ArchD, + ArchE, + + Imperial7x9, + Imperial8x10, + Imperial9x11, + Imperial9x12, + Imperial10x11, + Imperial10x13, + Imperial10x14, + Imperial12x11, + Imperial15x11, + + ExecutiveStandard, + Note, + Quarto, + Statement, + SuperA, + SuperB, + Postcard, + DoublePostcard, + Prc16K, + Prc32K, + Prc32KBig, + + FanFoldUS, + FanFoldGerman, + FanFoldGermanLegal, + + EnvelopeB4, + EnvelopeB5, + EnvelopeB6, + EnvelopeC0, + EnvelopeC1, + EnvelopeC2, + EnvelopeC3, + EnvelopeC4, + // EnvelopeC5 = C5E, + EnvelopeC6, + EnvelopeC65, + EnvelopeC7, + // EnvelopeDL = DLE, + + Envelope9, + // Envelope10 = Comm10E, + Envelope11, + Envelope12, + Envelope14, + EnvelopeMonarch, + EnvelopePersonal, + + EnvelopeChou3, + EnvelopeChou4, + EnvelopeInvite, + EnvelopeItalian, + EnvelopeKaku2, + EnvelopeKaku3, + EnvelopePrc1, + EnvelopePrc2, + EnvelopePrc3, + EnvelopePrc4, + EnvelopePrc5, + EnvelopePrc6, + EnvelopePrc7, + EnvelopePrc8, + EnvelopePrc9, + EnvelopePrc10, + EnvelopeYou4, + + // Last item, with commonly used synynoms from QPagedPrintEngine / QPrinter + LastPageSize = EnvelopeYou4, + NPageSize = LastPageSize, + NPaperSize = LastPageSize, + + // Convenience overloads for naming consistency + AnsiA = Letter, + AnsiB = Ledger, + EnvelopeC5 = C5E, + EnvelopeDL = DLE, + Envelope10 = Comm10E + }; #endif enum PageOrder { FirstPageFirst, -- cgit v1.2.3 From 0c04b31d2715f68aa883107b4aa593fd95aefdfe Mon Sep 17 00:00:00 2001 From: John Layt Date: Sun, 29 Dec 2013 20:19:48 +0100 Subject: QPdfPaintEngine - Use QPageLayout and QPageSize Switch internals of QPdfPageEngine and derived classes to use QPageLayout and QPageSize to make handling of page layout and size more consistent by removing multiple implementations. In particular remove all use of the QPdf namespace version of page size. Change-Id: Ie820340015e8812c8162bd1a257dd0f51f4f0b85 Reviewed-by: Lars Knoll --- src/gui/painting/qpagesize.h | 1 + src/gui/painting/qpdf.cpp | 104 +++++++++--------- src/gui/painting/qpdf_p.h | 39 +++---- src/gui/painting/qpdfwriter.cpp | 10 +- src/plugins/printsupport/cups/qcupsprintengine.cpp | 115 +++++++------------- src/plugins/printsupport/cups/qcupsprintengine_p.h | 6 +- src/printsupport/dialogs/qpagesetupdialog_unix.cpp | 4 +- src/printsupport/kernel/qprintengine_pdf.cpp | 119 +++++++-------------- src/printsupport/kernel/qprintengine_pdf_p.h | 15 --- 9 files changed, 156 insertions(+), 257 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h index c8a472747d..2e88d497a9 100644 --- a/src/gui/painting/qpagesize.h +++ b/src/gui/painting/qpagesize.h @@ -290,6 +290,7 @@ public: private: friend class QPageSizePrivate; friend class QPlatformPrintDevice; + friend class QCupsPrintEnginePrivate; QPageSize(const QString &key, const QSize &pointSize, const QString &name); QPageSize(int windowsId, const QSize &pointSize, const QString &name); QPageSize(QPageSizePrivate &dd); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 147fa3f561..56cfc0f707 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1425,19 +1425,60 @@ QPaintEngine::Type QPdfEngine::type() const return QPaintEngine::Pdf; } +void QPdfEngine::setResolution(int resolution) +{ + Q_D(QPdfEngine); + d->resolution = resolution; +} + +int QPdfEngine::resolution() const +{ + Q_D(const QPdfEngine); + return d->resolution; +} + +void QPdfEngine::setPageLayout(const QPageLayout &pageLayout) +{ + Q_D(QPdfEngine); + d->m_pageLayout = pageLayout; +} +void QPdfEngine::setPageSize(const QPageSize &pageSize) +{ + Q_D(QPdfEngine); + d->m_pageLayout.setPageSize(pageSize); +} + +void QPdfEngine::setPageOrientation(QPageLayout::Orientation orientation) +{ + Q_D(QPdfEngine); + d->m_pageLayout.setOrientation(orientation); +} + +void QPdfEngine::setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) +{ + Q_D(QPdfEngine); + d->m_pageLayout.setUnits(units); + d->m_pageLayout.setMargins(margins); +} +QPageLayout QPdfEngine::pageLayout() const +{ + Q_D(const QPdfEngine); + return d->m_pageLayout; +} + +// Metrics are in Device Pixels int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const { Q_D(const QPdfEngine); int val; - QRect r = d->pageRect(); switch (metricType) { case QPaintDevice::PdmWidth: - val = r.width(); + val = d->m_pageLayout.paintRectPixels(d->resolution).width(); break; case QPaintDevice::PdmHeight: - val = r.height(); + val = d->m_pageLayout.paintRectPixels(d->resolution).height(); break; case QPaintDevice::PdmDpiX: case QPaintDevice::PdmDpiY: @@ -1448,10 +1489,10 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const val = 1200; break; case QPaintDevice::PdmWidthMM: - val = qRound(r.width()*25.4/d->resolution); + val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).width()); break; case QPaintDevice::PdmHeightMM: - val = qRound(r.height()*25.4/d->resolution); + val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).height()); break; case QPaintDevice::PdmNumColors: val = INT_MAX; @@ -1469,21 +1510,12 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const return val; } -static inline QSizeF pageSizeToPostScriptPoints(const QSizeF &pageSizeMM) -{ -#define Q_MM(n) int((n * 720 + 127) / 254) - return QSizeF(Q_MM(pageSizeMM.width()), Q_MM(pageSizeMM.height())); -#undef Q_MM -} - QPdfEnginePrivate::QPdfEnginePrivate() : clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false), outDevice(0), ownsDevice(false), - fullPage(false), embedFonts(true), - landscape(false), + embedFonts(true), grayscale(false), - paperSize(pageSizeToPostScriptPoints(QSizeF(210, 297))), // A4 - leftMargin(10), topMargin(10), rightMargin(10), bottomMargin(10) // ~3.5 mm + m_pageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(10, 10, 10, 10)) { resolution = 1200; currentObject = 1; @@ -1495,11 +1527,6 @@ QPdfEnginePrivate::QPdfEnginePrivate() stream = new QDataStream; } -void QPdfEnginePrivate::setPaperSize(const QSizeF &pageSizeMM) -{ - paperSize = pageSizeToPostScriptPoints(pageSizeMM); -} - bool QPdfEngine::begin(QPaintDevice *pdev) { Q_D(QPdfEngine); @@ -1581,31 +1608,6 @@ QPdfEnginePrivate::~QPdfEnginePrivate() delete stream; } -QRect QPdfEnginePrivate::paperRect() const -{ - int w = qRound(paperSize.width()*resolution/72.); - int h = qRound(paperSize.height()*resolution/72.); - - if (!landscape) - return QRect(0, 0, w, h); - else - return QRect(0, 0, h, w); -} - -QRect QPdfEnginePrivate::pageRect() const -{ - QRect r = paperRect(); - - if(!fullPage) - r.adjust(qRound(leftMargin*(resolution/72.)), - qRound(topMargin*(resolution/72.)), - -qRound(rightMargin*(resolution/72.)), - -qRound(bottomMargin*(resolution/72.))); - - return r; -} - - void QPdfEnginePrivate::writeHeader() { addXrefEntry(0,false); @@ -2615,9 +2617,9 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) QTransform QPdfEnginePrivate::pageMatrix() const { qreal scale = 72./resolution; - QTransform tmp(scale, 0.0, 0.0, -scale, 0.0, height()); - if (!fullPage) { - QRect r = pageRect(); + QTransform tmp(scale, 0.0, 0.0, -scale, 0.0, m_pageLayout.fullRectPoints().height()); + if (m_pageLayout.mode() != QPageLayout::FullPageMode) { + QRect r = m_pageLayout.paintRectPixels(resolution); tmp.translate(r.left(), r.top()); } return tmp; @@ -2626,12 +2628,12 @@ QTransform QPdfEnginePrivate::pageMatrix() const void QPdfEnginePrivate::newPage() { if (currentPage && currentPage->pageSize.isEmpty()) - currentPage->pageSize = QSize(width(), height()); + currentPage->pageSize = m_pageLayout.fullRectPoints().size(); writePage(); delete currentPage; currentPage = new QPdfPage; - currentPage->pageSize = QSize(width(), height()); + currentPage->pageSize = m_pageLayout.fullRectPoints().size(); stroker.stream = currentPage; pages.append(requestObject()); diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h index ae2d4b00ac..e9459eff83 100644 --- a/src/gui/painting/qpdf_p.h +++ b/src/gui/painting/qpdf_p.h @@ -64,6 +64,7 @@ #include "private/qpaintengine_p.h" #include "private/qfontengine_p.h" #include "private/qfontsubset_p.h" +#include "qpagelayout.h" // #define USE_NATIVE_GRADIENTS @@ -179,7 +180,9 @@ public: ~QPdfEngine() {} void setOutputFilename(const QString &filename); - inline void setResolution(int resolution); + + void setResolution(int resolution); + int resolution() const; // reimplementations QPaintEngine bool begin(QPaintDevice *pdev); @@ -207,6 +210,14 @@ public: // Printer stuff... bool newPage(); + // Page layout stuff + void setPageLayout(const QPageLayout &pageLayout); + void setPageSize(const QPageSize &pageSize); + void setPageOrientation(QPageLayout::Orientation orientation); + void setPageMargins(const QMarginsF &margins, QPageLayout::Unit units = QPageLayout::Point); + + QPageLayout pageLayout() const; + void setPen(); void setBrush(); void setupGraphicsState(QPaintEngine::DirtyFlags flags); @@ -224,19 +235,6 @@ public: inline uint requestObject() { return currentObject++; } - QRect paperRect() const; - QRect pageRect() const; - void setPaperSize(const QSizeF &pageSizeMM); - - int width() const { - QRect r = paperRect(); - return qRound(r.width()*72./resolution); - } - int height() const { - QRect r = paperRect(); - return qRound(r.height()*72./resolution); - } - void writeHeader(); void writeTail(); @@ -278,15 +276,12 @@ public: QString outputFileName; QString title; QString creator; - bool fullPage; bool embedFonts; int resolution; - bool landscape; bool grayscale; - // in postscript points - QSizeF paperSize; - qreal leftMargin, topMargin, rightMargin, bottomMargin; + // Page layout: size, orientation and margins + QPageLayout m_pageLayout; private: #ifdef USE_NATIVE_GRADIENTS @@ -325,12 +320,6 @@ private: QHash, uint > alphaCache; }; -void QPdfEngine::setResolution(int resolution) -{ - Q_D(QPdfEngine); - d->resolution = resolution; -} - QT_END_NAMESPACE #endif // QT_NO_PDF diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp index 27fb8b1646..a6f752b129 100644 --- a/src/gui/painting/qpdfwriter.cpp +++ b/src/gui/painting/qpdfwriter.cpp @@ -166,7 +166,7 @@ void QPdfWriter::setPageSize(PageSize size) Q_D(const QPdfWriter); QPagedPaintDevice::setPageSize(size); - d->engine->d_func()->setPaperSize(pageSizeMM()); + d->engine->setPageSize(QPageSize(QPageSize::PageSizeId(size))); } /*! @@ -177,7 +177,7 @@ void QPdfWriter::setPageSizeMM(const QSizeF &size) Q_D(const QPdfWriter); QPagedPaintDevice::setPageSizeMM(size); - d->engine->d_func()->setPaperSize(pageSizeMM()); + d->engine->setPageSize(QPageSize(size, QPageSize::Millimeter)); } /*! @@ -212,10 +212,8 @@ void QPdfWriter::setMargins(const Margins &m) QPagedPaintDevice::setMargins(m); const qreal multiplier = 72./25.4; - d->engine->d_func()->leftMargin = m.left*multiplier; - d->engine->d_func()->rightMargin = m.right*multiplier; - d->engine->d_func()->topMargin = m.top*multiplier; - d->engine->d_func()->bottomMargin = m.bottom*multiplier; + d->engine->setPageMargins(QMarginsF(m.left * multiplier, m.top * multiplier, + m.right * multiplier, m.bottom * multiplier), QPageLayout::Point); } QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 2fecdc00e9..c41ee4373c 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE +extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits); + QCupsPrintEngine::QCupsPrintEngine(QPrinter::PrinterMode m) : QPdfPrintEngine(*new QCupsPrintEnginePrivate(m)) { @@ -89,9 +91,8 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v Q_D(QCupsPrintEngine); switch (int(key)) { - case PPK_PaperSize: - d->printerPaperSize = QPrinter::PaperSize(value.toInt()); - d->setPaperSize(); + case PPK_PageSize: + d->setPageSize(QPageSize::PageSizeId(value.toInt())); break; case PPK_CupsPageRect: d->cupsPageRect = value.toRect(); @@ -104,8 +105,7 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v break; case PPK_CupsStringPageSize: case PPK_PaperName: - d->cupsStringPageSize = value.toString(); - d->setPaperName(); + d->setPaperName(value.toString()); break; case PPK_PrinterName: // prevent setting the defaults again for the same printer @@ -143,7 +143,7 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_CupsStringPageSize: case PPK_PaperName: - ret = d->cupsStringPageSize; + ret = d->m_pageLayout.pageSize().name(); break; default: ret = QPdfPrintEngine::property(key); @@ -215,8 +215,7 @@ void QCupsPrintEnginePrivate::closePrintDevice() prnName = def.printerName().toLocal8Bit(); } - if (!cupsStringPageSize.isEmpty()) - options.append(QPair("media", cupsStringPageSize.toLocal8Bit())); + options.append(QPair("media", m_pageLayout.pageSize().key().toLocal8Bit())); if (copies > 1) options.append(QPair("copies", QString::number(copies).toLocal8Bit())); @@ -229,7 +228,7 @@ void QCupsPrintEnginePrivate::closePrintDevice() options.append(QPair("sides", "one-sided")); break; case QPrinter::DuplexAuto: - if (!landscape) + if (m_pageLayout.orientation() == QPageLayout::Portrait) options.append(QPair("sides", "two-sided-long-edge")); else options.append(QPair("sides", "two-sided-short-edge")); @@ -242,7 +241,7 @@ void QCupsPrintEnginePrivate::closePrintDevice() break; } - if (QCUPSSupport::cupsVersion() >= 10300 && landscape) + if (QCUPSSupport::cupsVersion() >= 10300 && m_pageLayout.orientation() == QPageLayout::Landscape) options.append(QPair("landscape", "")); QStringList::const_iterator it = cupsOptions.constBegin(); @@ -267,43 +266,25 @@ void QCupsPrintEnginePrivate::closePrintDevice() } } -void QCupsPrintEnginePrivate::updatePaperSize() -{ - if (printerPaperSize == QPrinter::Custom) { - paperSize = customPaperSize; - } else if (!cupsPaperRect.isNull()) { - QRect r = cupsPaperRect; - paperSize = r.size(); - } else { - QPdf::PaperSize s = QPdf::paperSize(printerPaperSize); - paperSize = QSize(s.width, s.height); - } -} - -void QCupsPrintEnginePrivate::setPaperSize() +void QCupsPrintEnginePrivate::setPageSize(QPageSize::PageSizeId pageSizeId) { if (QCUPSSupport::isAvailable()) { QCUPSSupport cups; - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(printerPaperSize)); + QSize size = QPageSize(pageSizeId).sizePoints(); if (cups.currentPPD()) { - cupsStringPageSize = QLatin1String("Custom"); const ppd_option_t* pageSizes = cups.pageSizes(); for (int i = 0; i < pageSizes->num_choices; ++i) { QByteArray cupsPageSize = pageSizes->choices[i].choice; QRect tmpCupsPaperRect = cups.paperRect(cupsPageSize); QRect tmpCupsPageRect = cups.pageRect(cupsPageSize); - if (qAbs(size.width - tmpCupsPaperRect.width()) < 5 && qAbs(size.height - tmpCupsPaperRect.height()) < 5) { + if (qAbs(size.width() - tmpCupsPaperRect.width()) < 5 && qAbs(size.height() - tmpCupsPaperRect.height()) < 5) { + QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); + QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); cupsPaperRect = tmpCupsPaperRect; cupsPageRect = tmpCupsPageRect; - cupsStringPageSize = pageSizes->choices[i].text; - leftMargin = cupsPageRect.x() - cupsPaperRect.x(); - topMargin = cupsPageRect.y() - cupsPaperRect.y(); - rightMargin = cupsPaperRect.right() - cupsPageRect.right(); - bottomMargin = cupsPaperRect.bottom() - cupsPageRect.bottom(); - - updatePaperSize(); + setPageSize(key, name); break; } } @@ -311,39 +292,22 @@ void QCupsPrintEnginePrivate::setPaperSize() } } -void QCupsPrintEnginePrivate::setPaperName() +void QCupsPrintEnginePrivate::setPaperName(const QString &paperName) { if (QCUPSSupport::isAvailable()) { QCUPSSupport cups; if (cups.currentPPD()) { const ppd_option_t* pageSizes = cups.pageSizes(); - bool foundPaperName = false; for (int i = 0; i < pageSizes->num_choices; ++i) { - if (cupsStringPageSize == pageSizes->choices[i].text) { - foundPaperName = true; - QByteArray cupsPageSize = pageSizes->choices[i].choice; - cupsPaperRect = cups.paperRect(cupsPageSize); - cupsPageRect = cups.pageRect(cupsPageSize); - leftMargin = cupsPageRect.x() - cupsPaperRect.x(); - topMargin = cupsPageRect.y() - cupsPaperRect.y(); - rightMargin = cupsPaperRect.right() - cupsPageRect.right(); - bottomMargin = cupsPaperRect.bottom() - cupsPageRect.bottom(); - printerPaperSize = QPrinter::Custom; - customPaperSize = cupsPaperRect.size(); - for (int ps = 0; ps < QPrinter::NPageSize; ++ps) { - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps)); - if (qAbs(size.width - cupsPaperRect.width()) < 5 && qAbs(size.height - cupsPaperRect.height()) < 5) { - printerPaperSize = static_cast(ps); - customPaperSize = QSize(); - break; - } - } - updatePaperSize(); + if (pageSizes->choices[i].text == paperName) { + QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); + QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); + cupsPaperRect = cups.paperRect(pageSizes->choices[i].choice); + cupsPageRect = cups.pageRect(pageSizes->choices[i].choice); + setPageSize(key, name); break; } } - if (!foundPaperName) - cupsStringPageSize = QString(); } } } @@ -390,33 +354,30 @@ void QCupsPrintEnginePrivate::setCupsDefaults() QByteArray cupsPageSize; for (int i = 0; i < pageSizes->num_choices; ++i) { if (static_cast(pageSizes->choices[i].marked) == 1) { - cupsPageSize = pageSizes->choices[i].choice; - cupsStringPageSize = pageSizes->choices[i].text; + QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); + QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); + cupsPaperRect = cups.paperRect(pageSizes->choices[i].choice); + cupsPageRect = cups.pageRect(pageSizes->choices[i].choice); + setPageSize(key, name); } } cupsOptions = cups.options(); - cupsPaperRect = cups.paperRect(cupsPageSize); - cupsPageRect = cups.pageRect(cupsPageSize); - - for (int ps = 0; ps < QPrinter::NPageSize; ++ps) { - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps)); - if (qAbs(size.width - cupsPaperRect.width()) < 5 && qAbs(size.height - cupsPaperRect.height()) < 5) { - printerPaperSize = static_cast(ps); - - leftMargin = cupsPageRect.x() - cupsPaperRect.x(); - topMargin = cupsPageRect.y() - cupsPaperRect.y(); - rightMargin = cupsPaperRect.right() - cupsPageRect.right(); - bottomMargin = cupsPaperRect.bottom() - cupsPageRect.bottom(); - - updatePaperSize(); - break; - } - } } } } +void QCupsPrintEnginePrivate::setPageSize(const QString &key, const QString &name) +{ + QSize size = QSize(cupsPaperRect.width(), cupsPaperRect.height()); + const qreal left = cupsPageRect.x() - cupsPaperRect.x(); + const qreal top = cupsPageRect.y() - cupsPaperRect.y(); + const qreal right = cupsPaperRect.right() - cupsPageRect.right(); + const qreal bottom = cupsPaperRect.bottom() - cupsPageRect.bottom(); + QMarginsF printable = qt_convertMargins(QMarginsF(left, top, right, bottom), + QPageLayout::Point, m_pageLayout.units()); + m_pageLayout.setPageSize(QPageSize(key, size, name), printable); +} QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h index db947a0232..bc85205d50 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine_p.h +++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h @@ -96,15 +96,15 @@ public: void closePrintDevice(); void updatePaperSize(); - void setPaperSize(); - void setPaperName(); + void setPageSize(QPageSize::PageSizeId pageSizeId); + void setPaperName(const QString &name); void setCupsDefaults(); + void setPageSize(const QString &key, const QString &name); private: Q_DISABLE_COPY(QCupsPrintEnginePrivate) QStringList cupsOptions; - QString cupsStringPageSize; QRect cupsPaperRect; QRect cupsPageRect; QString cupsTempFile; diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp index 6801863a3a..d2975ad9da 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp @@ -371,8 +371,8 @@ void QPageSetupWidget::setupPrinter() const #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) else if (val.type() == QVariant::ByteArray) { for (int papersize = 0; papersize < QPrinter::NPageSize; ++papersize) { - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(papersize)); - if (size.width == m_paperSize.width() && size.height == m_paperSize.height()) { + QSize size = QPageSize(QPageSize::PageSizeId(papersize)).sizePoints(); + if (size.width() == m_paperSize.width() && size.height() == m_paperSize.height()) { ps = static_cast(papersize); break; } diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp index 6c65300462..2ddfb9c49e 100644 --- a/src/printsupport/kernel/qprintengine_pdf.cpp +++ b/src/printsupport/kernel/qprintengine_pdf.cpp @@ -63,34 +63,6 @@ QT_BEGIN_NAMESPACE -//#define FONT_DUMP - -extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size); - -#define Q_MM(n) int((n * 720 + 127) / 254) -#define Q_IN(n) int(n * 72) - -static const char * const psToStr[QPrinter::NPageSize+1] = -{ - "A4", "B5", "Letter", "Legal", "Executive", - "A0", "A1", "A2", "A3", "A5", "A6", "A7", "A8", "A9", "B0", "B1", - "B10", "B2", "B3", "B4", "B6", "B7", "B8", "B9", "C5E", "Comm10E", - "DLE", "Folio", "Ledger", "Tabloid", 0 -}; - -QPdf::PaperSize QPdf::paperSize(QPrinter::PaperSize paperSize) -{ - QSizeF s = qt_paperSizeToQSizeF(paperSize); - PaperSize p = { Q_MM(s.width()), Q_MM(s.height()) }; - return p; -} - -const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize) -{ - return psToStr[paperSize]; -} - - QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m) : QPdfEngine(*new QPdfPrintEnginePrivate(m)) { @@ -163,8 +135,6 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va // The following keys are settings that are unsupported by the PDF PrintEngine case PPK_CustomBase: break; - case PPK_PaperName: - break; case PPK_WindowsPageSize: break; @@ -182,14 +152,17 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->title = value.toString(); break; case PPK_FullPage: - d->fullPage = value.toBool(); + if (value.toBool()) + d->m_pageLayout.setMode(QPageLayout::FullPageMode); + else + d->m_pageLayout.setMode(QPageLayout::StandardMode); break; case PPK_CopyCount: // fallthrough case PPK_NumberOfCopies: d->copies = value.toInt(); break; case PPK_Orientation: - d->landscape = (QPrinter::Orientation(value.toInt()) == QPrinter::Landscape); + d->m_pageLayout.setOrientation(QPageLayout::Orientation(value.toInt())); break; case PPK_OutputFileName: d->outputFileName = value.toString(); @@ -197,10 +170,23 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_PageOrder: d->pageOrder = QPrinter::PageOrder(value.toInt()); break; - case PPK_PaperSize: - d->printerPaperSize = QPrinter::PaperSize(value.toInt()); - d->updatePaperSize(); + case PPK_PageSize: { + QPageSize pageSize = QPageSize(QPageSize::PageSizeId(value.toInt())); + if (pageSize.isValid()) + d->m_pageLayout.setPageSize(pageSize); break; + } + case PPK_PaperName: { + QString name = value.toString(); + for (int i = 0; i <= QPageSize::LastPageSize; ++i) { + QPageSize pageSize = QPageSize(QPageSize::PageSizeId(i)); + if (name == pageSize.name()) { + d->m_pageLayout.setPageSize(pageSize); + break; + } + } + break; + } case PPK_PaperSource: d->paperSource = QPrinter::PaperSource(value.toInt()); break; @@ -223,19 +209,14 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->duplex = static_cast (value.toInt()); break; case PPK_CustomPaperSize: - d->printerPaperSize = QPrinter::Custom; - d->customPaperSize = value.toSizeF(); - d->updatePaperSize(); + d->m_pageLayout.setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); break; - case PPK_PageMargins: - { + case PPK_PageMargins: { QList margins(value.toList()); Q_ASSERT(margins.size() == 4); - d->leftMargin = margins.at(0).toReal(); - d->topMargin = margins.at(1).toReal(); - d->rightMargin = margins.at(2).toReal(); - d->bottomMargin = margins.at(3).toReal(); - d->pageMarginsSet = true; + d->m_pageLayout.setUnits(QPageLayout::Point); + d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(), + margins.at(2).toReal(), margins.at(3).toReal())); break; } // No default so that compiler will complain if new keys added and not handled in this engine @@ -254,9 +235,6 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const case PPK_CustomBase: // Special case, leave null break; - case PPK_PaperName: - ret = QString(); - break; case PPK_WindowsPageSize: // Special case, leave null break; @@ -275,7 +253,7 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const ret = d->title; break; case PPK_FullPage: - ret = d->fullPage; + ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode; break; case PPK_CopyCount: ret = d->copies; @@ -287,7 +265,7 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const ret = d->copies; break; case PPK_Orientation: - ret = d->landscape ? QPrinter::Landscape : QPrinter::Portrait; + ret = d->m_pageLayout.orientation(); break; case PPK_OutputFileName: ret = d->outputFileName; @@ -295,8 +273,11 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const case PPK_PageOrder: ret = d->pageOrder; break; - case PPK_PaperSize: - ret = d->printerPaperSize; + case PPK_PageSize: + ret = d->m_pageLayout.pageSize().id(); + break; + case PPK_PaperName: + ret = d->m_pageLayout.pageSize().name(); break; case PPK_PaperSource: ret = d->paperSource; @@ -314,10 +295,10 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const ret = QList() << 72; break; case PPK_PaperRect: - ret = d->paperRect(); + ret = d->m_pageLayout.fullRectPixels(d->resolution); break; case PPK_PageRect: - ret = d->pageRect(); + ret = d->m_pageLayout.paintRectPixels(d->resolution); break; case PPK_SelectionOption: ret = d->selectionOption; @@ -329,17 +310,13 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const ret = d->duplex; break; case PPK_CustomPaperSize: - ret = d->customPaperSize; + ret = d->m_pageLayout.fullRectPoints().size(); break; - case PPK_PageMargins: - { - QList margins; - if (d->printerPaperSize == QPrinter::Custom && !d->pageMarginsSet) - margins << 0 << 0 << 0 << 0; - else - margins << d->leftMargin << d->topMargin - << d->rightMargin << d->bottomMargin; - ret = margins; + case PPK_PageMargins: { + QList list; + QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point); + list << margins.left() << margins.top() << margins.right() << margins.bottom(); + ret = list; break; } // No default so that compiler will complain if new keys added and not handled in this engine @@ -390,8 +367,6 @@ QPdfPrintEnginePrivate::QPdfPrintEnginePrivate(QPrinter::PrinterMode m) copies(1), pageOrder(QPrinter::FirstPageFirst), paperSource(QPrinter::Auto), - printerPaperSize(QPrinter::A4), - pageMarginsSet(false), fd(-1) { resolution = 72; @@ -405,18 +380,6 @@ QPdfPrintEnginePrivate::~QPdfPrintEnginePrivate() { } - -void QPdfPrintEnginePrivate::updatePaperSize() -{ - if (printerPaperSize == QPrinter::Custom) { - paperSize = customPaperSize; - } else { - QPdf::PaperSize s = QPdf::paperSize(printerPaperSize); - paperSize = QSize(s.width, s.height); - } -} - - QT_END_NAMESPACE #endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprintengine_pdf_p.h b/src/printsupport/kernel/qprintengine_pdf_p.h index eec6d48181..cc4044d1a0 100644 --- a/src/printsupport/kernel/qprintengine_pdf_p.h +++ b/src/printsupport/kernel/qprintengine_pdf_p.h @@ -77,16 +77,6 @@ class QPen; class QPointF; class QRegion; class QFile; -class QPdfPrintEngine; - -namespace QPdf { - - struct PaperSize { - int width, height; // in postscript points - }; - Q_PRINTSUPPORT_EXPORT PaperSize paperSize(QPrinter::PaperSize paperSize); - Q_PRINTSUPPORT_EXPORT const char *paperSizeToString(QPrinter::PaperSize paperSize); -} class QPdfPrintEnginePrivate; @@ -131,8 +121,6 @@ public: virtual bool openPrintDevice(); virtual void closePrintDevice(); - virtual void updatePaperSize(); - private: Q_DISABLE_COPY(QPdfPrintEnginePrivate) @@ -149,9 +137,6 @@ private: QPrinter::PageOrder pageOrder; QPrinter::PaperSource paperSource; - QPrinter::PaperSize printerPaperSize; - QSizeF customPaperSize; // in postscript points - bool pageMarginsSet; int fd; }; -- cgit v1.2.3 From 9e29fab38df831f33385ee25bff235a620aa20d5 Mon Sep 17 00:00:00 2001 From: John Layt Date: Sun, 5 Jan 2014 18:51:32 +0100 Subject: QPdfWriter - Use QPageSize and QPageLayout Add support to QPdfWriter for QPageSize, QPageLayout, and resolution. [ChangeLog][QtGui][QPdfWriter] The QPdfWriter now supports setting the PDF orientation, layout and resolution by using QPageSize and QPageLayout. Change-Id: I9c269f997ec540dac1989f355c6a2e7488947966 Reviewed-by: Lars Knoll --- src/gui/painting/qpdfwriter.cpp | 229 ++++++++++++++++++++++++++++++++++++---- src/gui/painting/qpdfwriter.h | 12 +++ 2 files changed, 222 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp index a6f752b129..08c8f42fd9 100644 --- a/src/gui/painting/qpdfwriter.cpp +++ b/src/gui/painting/qpdfwriter.cpp @@ -90,6 +90,9 @@ QPdfWriter::QPdfWriter(const QString &filename) Q_D(QPdfWriter); d->engine->setOutputFilename(filename); + + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); } /*! @@ -101,6 +104,9 @@ QPdfWriter::QPdfWriter(QIODevice *device) Q_D(QPdfWriter); d->engine->d_func()->outDevice = device; + + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); } /*! @@ -147,7 +153,6 @@ void QPdfWriter::setCreator(const QString &creator) d->engine->d_func()->creator = creator; } - /*! \reimp */ @@ -159,25 +164,213 @@ QPaintEngine *QPdfWriter::paintEngine() const } /*! - \reimp - */ -void QPdfWriter::setPageSize(PageSize size) + \since 5.3 + + Sets the PDF \a resolution in DPI. + + This setting affects the coordinate system as returned by, for + example QPainter::viewport(). + + \sa resolution() +*/ + +void QPdfWriter::setResolution(int resolution) { Q_D(const QPdfWriter); + if (resolution > 0) + d->engine->setResolution(resolution); +} + +/*! + \since 5.3 - QPagedPaintDevice::setPageSize(size); - d->engine->setPageSize(QPageSize(QPageSize::PageSizeId(size))); + Returns the resolution of the PDF in DPI. + + \sa setResolution() +*/ + +int QPdfWriter::resolution() const +{ + Q_D(const QPdfWriter); + return d->engine->resolution(); } /*! - \reimp - */ -void QPdfWriter::setPageSizeMM(const QSizeF &size) + \since 5.3 + + Sets the PDF page layout to \a newPageLayout. + + You should call this before calling QPainter::begin(), or immediately + before calling newPage() to apply the new page layout to a new page. + You should not call any painting methods between a call to setPageLayout() + and newPage() as the wrong paint metrics may be used. + + Returns true if the page layout was successfully set to \a newPageLayout. + + \sa pageLayout() +*/ + +bool QPdfWriter::setPageLayout(const QPageLayout &newPageLayout) { Q_D(const QPdfWriter); + // Try to set the paint engine page layout + d->engine->setPageLayout(newPageLayout); + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); + return pageLayout().isEquivalentTo(newPageLayout); +} + +/*! + \since 5.3 + + Sets the PDF page size to \a pageSize. + + To get the current QPageSize use pageLayout().pageSize(). + + You should call this before calling QPainter::begin(), or immediately + before calling newPage() to apply the new page size to a new page. + You should not call any painting methods between a call to setPageSize() + and newPage() as the wrong paint metrics may be used. + + Returns true if the page size was successfully set to \a pageSize. - QPagedPaintDevice::setPageSizeMM(size); - d->engine->setPageSize(QPageSize(size, QPageSize::Millimeter)); + \sa pageLayout() +*/ + +bool QPdfWriter::setPageSize(const QPageSize &pageSize) +{ + Q_D(const QPdfWriter); + // Try to set the paint engine page size + d->engine->setPageSize(pageSize); + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); + return pageLayout().pageSize().isEquivalentTo(pageSize); +} + +/*! + \since 5.3 + + Sets the PDF page \a orientation. + + The page orientation is used to define the orientation of the + page size when obtaining the page rect. + + You should call this before calling QPainter::begin(), or immediately + before calling newPage() to apply the new orientation to a new page. + You should not call any painting methods between a call to setPageOrientation() + and newPage() as the wrong paint metrics may be used. + + To get the current QPageLayout::Orientation use pageLayout().pageOrientation(). + + Returns true if the page orientation was successfully set to \a orientation. + + \sa pageLayout() +*/ + +bool QPdfWriter::setPageOrientation(QPageLayout::Orientation orientation) +{ + Q_D(const QPdfWriter); + // Set the print engine value + d->engine->setPageOrientation(orientation); + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); + return pageLayout().orientation() == orientation; +} + +/*! + \since 5.3 + + Set the PDF page \a margins in the current page layout units. + + You should call this before calling QPainter::begin(), or immediately + before calling newPage() to apply the new margins to a new page. + You should not call any painting methods between a call to setPageMargins() + and newPage() as the wrong paint metrics may be used. + + To get the current page margins use pageLayout().pageMargins(). + + Returns true if the page margins were successfully set to \a margins. + + \sa pageLayout() +*/ + +bool QPdfWriter::setPageMargins(const QMarginsF &margins) +{ + Q_D(const QPdfWriter); + // Try to set engine margins + d->engine->setPageMargins(margins, pageLayout().units()); + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); + return pageLayout().margins() == margins; +} + +/*! + \since 5.3 + + Set the PDF page \a margins defined in the given \a units. + + You should call this before calling QPainter::begin(), or immediately + before calling newPage() to apply the new margins to a new page. + You should not call any painting methods between a call to setPageMargins() + and newPage() as the wrong paint metrics may be used. + + To get the current page margins use pageLayout().pageMargins(). + + Returns true if the page margins were successfully set to \a margins. + + \sa pageLayout() +*/ + +bool QPdfWriter::setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) +{ + Q_D(const QPdfWriter); + // Try to set engine margins + d->engine->setPageMargins(margins, units); + // Set QPagedPaintDevice layout to match the current paint engine layout + devicePageLayout() = d->engine->pageLayout(); + return pageLayout().margins() == margins && pageLayout().units() == units; +} + +/*! + Returns the current page layout. Use this method to access the current + QPageSize, QPageLayout::Orientation, QMarginsF, fullRect() and paintRect(). + + Note that you cannot use the setters on the returned object, you must either + call the individual QPdfWriter methods or use setPageLayout(). + + \sa setPageLayout(), setPageSize(), setPageOrientation(), setPageMargins() +*/ + +QPageLayout QPdfWriter::pageLayout() const +{ + Q_D(const QPdfWriter); + return d->engine->pageLayout(); +} + +/*! + \reimp + + \obsolete Use setPageSize(QPageSize(id)) instead + + \sa setPageSize() +*/ + +void QPdfWriter::setPageSize(PageSize size) +{ + setPageSize(QPageSize(QPageSize::PageSizeId(size))); +} + +/*! + \reimp + + \obsolete Use setPageSize(QPageSize(size, QPageSize::Millimeter)) instead + + \sa setPageSize() +*/ + +void QPdfWriter::setPageSizeMM(const QSizeF &size) +{ + setPageSize(QPageSize(size, QPageSize::Millimeter)); } /*! @@ -203,17 +396,15 @@ bool QPdfWriter::newPage() /*! - \reimp + \reimp + + \obsolete Use setPageMargins(QMarginsF(l, t, r, b), QPageLayout::Millimeter) instead + + \sa setPageMargins() */ void QPdfWriter::setMargins(const Margins &m) { - Q_D(QPdfWriter); - - QPagedPaintDevice::setMargins(m); - - const qreal multiplier = 72./25.4; - d->engine->setPageMargins(QMarginsF(m.left * multiplier, m.top * multiplier, - m.right * multiplier, m.bottom * multiplier), QPageLayout::Point); + setPageMargins(QMarginsF(m.left, m.top, m.right, m.bottom), QPageLayout::Millimeter); } QT_END_NAMESPACE diff --git a/src/gui/painting/qpdfwriter.h b/src/gui/painting/qpdfwriter.h index f5c25de5e9..fce0b88ea8 100644 --- a/src/gui/painting/qpdfwriter.h +++ b/src/gui/painting/qpdfwriter.h @@ -48,6 +48,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -70,6 +71,17 @@ public: bool newPage(); + void setResolution(int resolution); + int resolution() const; + + bool setPageLayout(const QPageLayout &pageLayout); + bool setPageSize(const QPageSize &pageSize); + bool setPageOrientation(QPageLayout::Orientation orientation); + bool setPageMargins(const QMarginsF &margins); + bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units); + + QPageLayout pageLayout() const; + void setPageSize(PageSize size); void setPageSizeMM(const QSizeF &size); -- cgit v1.2.3 From d13195584e3ec4b3c30b626c360e81e437757427 Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 11 Dec 2013 16:37:03 +0100 Subject: QPrintEngine - Switch Cups to QPlaformPrintDevice Use QPlatformPrintDevice in the Cups print engine for all device specific code. Change-Id: Ic1f5f8b4010a9958c320f3c0c727cf1bd1a70c65 Reviewed-by: Lars Knoll --- src/gui/painting/qpagesize.h | 1 - src/plugins/printsupport/cups/qcupsprintengine.cpp | 272 ++++++++------------- src/plugins/printsupport/cups/qcupsprintengine_p.h | 16 +- src/printsupport/kernel/qcups_p.h | 3 - src/printsupport/kernel/qprintengine_pdf.cpp | 4 +- src/printsupport/kernel/qprintengine_pdf_p.h | 3 +- 6 files changed, 108 insertions(+), 191 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h index 2e88d497a9..c8a472747d 100644 --- a/src/gui/painting/qpagesize.h +++ b/src/gui/painting/qpagesize.h @@ -290,7 +290,6 @@ public: private: friend class QPageSizePrivate; friend class QPlatformPrintDevice; - friend class QCupsPrintEnginePrivate; QPageSize(const QString &key, const QSize &pointSize, const QString &name); QPageSize(int windowsId, const QSize &pointSize, const QString &name); QPageSize(QPageSizePrivate &dd); diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index c41ee4373c..2c05a76084 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -43,13 +43,17 @@ #ifndef QT_NO_PRINTER +#include +#include + #include #include #include #include -#include "private/qcups_p.h" -#include "qprinterinfo.h" +#include "private/qcups_p.h" // Only needed for PPK_CupsOptions +#include +#include #include #include @@ -63,22 +67,7 @@ QCupsPrintEngine::QCupsPrintEngine(QPrinter::PrinterMode m) : QPdfPrintEngine(*new QCupsPrintEnginePrivate(m)) { Q_D(QCupsPrintEngine); - - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - const cups_dest_t* printers = cups.availablePrinters(); - int prnCount = cups.availablePrintersCount(); - - for (int i = 0; i < prnCount; ++i) { - if (printers[i].is_default) { - d->printerName = QString::fromLocal8Bit(printers[i].name); - d->setCupsDefaults(); - break; - } - } - - } - + d->setupDefaultPrinter(); state = QPrinter::Idle; } @@ -92,27 +81,20 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v switch (int(key)) { case PPK_PageSize: - d->setPageSize(QPageSize::PageSizeId(value.toInt())); - break; - case PPK_CupsPageRect: - d->cupsPageRect = value.toRect(); - break; - case PPK_CupsPaperRect: - d->cupsPaperRect = value.toRect(); + d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt()))); break; - case PPK_CupsOptions: - d->cupsOptions = value.toStringList(); + case PPK_CustomPaperSize: + d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); break; - case PPK_CupsStringPageSize: case PPK_PaperName: - d->setPaperName(value.toString()); + // Get the named page size from the printer if supported + d->setPageSize(d->m_printDevice.supportedPageSize(value.toString())); break; case PPK_PrinterName: - // prevent setting the defaults again for the same printer - if (d->printerName != value.toString()) { - d->printerName = value.toString(); - d->setCupsDefaults(); - } + d->changePrinter(value.toString()); + break; + case PPK_CupsOptions: + d->cupsOptions = value.toStringList(); break; default: QPdfPrintEngine::setProperty(key, value); @@ -127,24 +109,15 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const QVariant ret; switch (int(key)) { case PPK_SupportsMultipleCopies: + // CUPS server always supports multiple copies, even if individual m_printDevice doesn't ret = true; break; case PPK_NumberOfCopies: ret = 1; break; - case PPK_CupsPageRect: - ret = d->cupsPageRect; - break; - case PPK_CupsPaperRect: - ret = d->cupsPaperRect; - break; case PPK_CupsOptions: ret = d->cupsOptions; break; - case PPK_CupsStringPageSize: - case PPK_PaperName: - ret = d->m_pageLayout.pageSize().name(); - break; default: ret = QPdfPrintEngine::property(key); break; @@ -173,17 +146,16 @@ bool QCupsPrintEnginePrivate::openPrintDevice() return false; } outDevice = file; - } else if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - QPair ret = cups.tempFd(); - if (ret.first < 0) { + } else { + char filename[512]; + fd = cupsTempFd(filename, 512); + if (fd < 0) { qWarning("QPdfPrinter: Could not open temporary file to print"); return false; } - cupsTempFile = ret.second; + cupsTempFile = QString::fromLocal8Bit(filename); outDevice = new QFile(); - static_cast(outDevice)->open(ret.first, QIODevice::WriteOnly); - fd = ret.first; + static_cast(outDevice)->open(fd, QIODevice::WriteOnly); } return true; @@ -196,25 +168,18 @@ void QCupsPrintEnginePrivate::closePrintDevice() if (!cupsTempFile.isEmpty()) { QString tempFile = cupsTempFile; cupsTempFile.clear(); - QCUPSSupport cups; + + // Should never have got here without a printer, but check anyway + if (printerName.isEmpty()) { + qWarning("Could not determine printer to print to"); + QFile::remove(tempFile); + return; + } // Set up print options. - QByteArray prnName; QList > options; QVector cupsOptStruct; - if (!printerName.isEmpty()) { - prnName = printerName.toLocal8Bit(); - } else { - QPrinterInfo def = QPrinterInfo::defaultPrinter(); - if (def.isNull()) { - qWarning("Could not determine printer to print to"); - QFile::remove(tempFile); - return; - } - prnName = def.printerName().toLocal8Bit(); - } - options.append(QPair("media", m_pageLayout.pageSize().key().toLocal8Bit())); if (copies > 1) @@ -224,24 +189,24 @@ void QCupsPrintEnginePrivate::closePrintDevice() options.append(QPair("Collate", "True")); switch (duplex) { - case QPrinter::DuplexNone: + case QPrint::DuplexNone: options.append(QPair("sides", "one-sided")); break; - case QPrinter::DuplexAuto: + case QPrint::DuplexAuto: if (m_pageLayout.orientation() == QPageLayout::Portrait) options.append(QPair("sides", "two-sided-long-edge")); else options.append(QPair("sides", "two-sided-short-edge")); break; - case QPrinter::DuplexLongSide: + case QPrint::DuplexLongSide: options.append(QPair("sides", "two-sided-long-edge")); break; - case QPrinter::DuplexShortSide: + case QPrint::DuplexShortSide: options.append(QPair("sides", "two-sided-short-edge")); break; } - if (QCUPSSupport::cupsVersion() >= 10300 && m_pageLayout.orientation() == QPageLayout::Landscape) + if (m_pageLayout.orientation() == QPageLayout::Landscape) options.append(QPair("landscape", "")); QStringList::const_iterator it = cupsOptions.constBegin(); @@ -259,124 +224,83 @@ void QCupsPrintEnginePrivate::closePrintDevice() // Print the file. cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0; - cups.printFile(prnName.constData(), tempFile.toLocal8Bit().constData(), - title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr); + cupsPrintFile(printerName.toLocal8Bit().constData(), tempFile.toLocal8Bit().constData(), + title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr); QFile::remove(tempFile); } } -void QCupsPrintEnginePrivate::setPageSize(QPageSize::PageSizeId pageSizeId) +void QCupsPrintEnginePrivate::setupDefaultPrinter() { - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - QSize size = QPageSize(pageSizeId).sizePoints(); - - if (cups.currentPPD()) { - const ppd_option_t* pageSizes = cups.pageSizes(); - for (int i = 0; i < pageSizes->num_choices; ++i) { - QByteArray cupsPageSize = pageSizes->choices[i].choice; - QRect tmpCupsPaperRect = cups.paperRect(cupsPageSize); - QRect tmpCupsPageRect = cups.pageRect(cupsPageSize); - - if (qAbs(size.width() - tmpCupsPaperRect.width()) < 5 && qAbs(size.height() - tmpCupsPaperRect.height()) < 5) { - QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); - QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); - cupsPaperRect = tmpCupsPaperRect; - cupsPageRect = tmpCupsPageRect; - setPageSize(key, name); - break; - } - } - } + // Should never have reached here if no plugin available, but check just in case + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return; + + // Get default printer id, if no default then use the first available + // TODO Find way to remove printerName from base class? + printerName = ps->defaultPrintDeviceId(); + if (printerName.isEmpty()) { + QStringList list = ps->availablePrintDeviceIds(); + if (list.size() > 0) + printerName = list.at(0); } -} -void QCupsPrintEnginePrivate::setPaperName(const QString &paperName) -{ - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - if (cups.currentPPD()) { - const ppd_option_t* pageSizes = cups.pageSizes(); - for (int i = 0; i < pageSizes->num_choices; ++i) { - if (pageSizes->choices[i].text == paperName) { - QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); - QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); - cupsPaperRect = cups.paperRect(pageSizes->choices[i].choice); - cupsPageRect = cups.pageRect(pageSizes->choices[i].choice); - setPageSize(key, name); - break; - } - } - } - } -} + // Should never have reached here if no printers available, but check just in case + if (printerName.isEmpty()) + return; -void QCupsPrintEnginePrivate::setCupsDefaults() -{ - if (QCUPSSupport::isAvailable()) { - int cupsPrinterIndex = -1; - QCUPSSupport cups; - - const cups_dest_t* printers = cups.availablePrinters(); - int prnCount = cups.availablePrintersCount(); - for (int i = 0; i < prnCount; ++i) { - QString name = QString::fromLocal8Bit(printers[i].name); - if (name == printerName) { - cupsPrinterIndex = i; - break; - } - } + m_printDevice = ps->createPrintDevice(printerName); + if (!m_printDevice.isValid()) + return; - if (cupsPrinterIndex < 0) - return; + // Setup the printer defaults + duplex = m_printDevice.defaultDuplexMode(); + grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale; + // CUPS server always supports collation, even if individual m_printDevice doesn't + collate = true; + setPageSize(m_printDevice.defaultPageSize()); +} - cups.setCurrentPrinter(cupsPrinterIndex); - - if (cups.currentPPD()) { - const ppd_option_t *ppdDuplex = cups.ppdOption("Duplex"); - if (ppdDuplex) { - if (qstrcmp(ppdDuplex->defchoice, "DuplexTumble") == 0) - duplex = QPrinter::DuplexShortSide; - else if (qstrcmp(ppdDuplex->defchoice, "DuplexNoTumble") == 0) - duplex = QPrinter::DuplexLongSide; - else - duplex = QPrinter::DuplexNone; - } - - grayscale = !cups.currentPPD()->color_device; - - const ppd_option_t *ppdCollate = cups.ppdOption("Collate"); - if (ppdCollate) - collate = qstrcmp(ppdCollate->defchoice, "True") == 0; - - const ppd_option_t* pageSizes = cups.pageSizes(); - QByteArray cupsPageSize; - for (int i = 0; i < pageSizes->num_choices; ++i) { - if (static_cast(pageSizes->choices[i].marked) == 1) { - QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); - QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); - cupsPaperRect = cups.paperRect(pageSizes->choices[i].choice); - cupsPageRect = cups.pageRect(pageSizes->choices[i].choice); - setPageSize(key, name); - } - } - - cupsOptions = cups.options(); - } - } +void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter) +{ + // Don't waste time if same printer name + if (newPrinter == printerName) + return; + + // Should never have reached here if no plugin available, but check just in case + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return; + + // Try create the printer, only use it if it returns valid + QPrintDevice printDevice = ps->createPrintDevice(newPrinter); + if (!m_printDevice.isValid()) + return; + m_printDevice.swap(printDevice); + printerName = m_printDevice.id(); + + // Check if new printer supports current settings, otherwise us defaults + if (duplex != QPrint::DuplexAuto && !m_printDevice.supportedDuplexModes().contains(duplex)) + duplex = m_printDevice.defaultDuplexMode(); + QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color; + if (!m_printDevice.supportedColorModes().contains(colorMode)) + grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale; + + // Get the equivalent page size for this printer as supported names may be different + setPageSize(m_pageLayout.pageSize()); } -void QCupsPrintEnginePrivate::setPageSize(const QString &key, const QString &name) +void QCupsPrintEnginePrivate::setPageSize(const QPageSize &pageSize) { - QSize size = QSize(cupsPaperRect.width(), cupsPaperRect.height()); - const qreal left = cupsPageRect.x() - cupsPaperRect.x(); - const qreal top = cupsPageRect.y() - cupsPaperRect.y(); - const qreal right = cupsPaperRect.right() - cupsPageRect.right(); - const qreal bottom = cupsPaperRect.bottom() - cupsPageRect.bottom(); - QMarginsF printable = qt_convertMargins(QMarginsF(left, top, right, bottom), - QPageLayout::Point, m_pageLayout.units()); - m_pageLayout.setPageSize(QPageSize(key, size, name), printable); + if (pageSize.isValid()) { + // Find if the requested page size has a matching printer page size, if so use its defined name instead + QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize); + QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize; + QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution); + m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units())); + } } QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h index bc85205d50..393fef42a3 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine_p.h +++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h @@ -61,9 +61,8 @@ #include #include +#include #include -#include -#include QT_BEGIN_NAMESPACE @@ -95,18 +94,15 @@ public: bool openPrintDevice(); void closePrintDevice(); - void updatePaperSize(); - void setPageSize(QPageSize::PageSizeId pageSizeId); - void setPaperName(const QString &name); - void setCupsDefaults(); - void setPageSize(const QString &key, const QString &name); - private: Q_DISABLE_COPY(QCupsPrintEnginePrivate) + void setupDefaultPrinter(); + void changePrinter(const QString &newPrinter); + void setPageSize(const QPageSize &pageSize); + + QPrintDevice m_printDevice; QStringList cupsOptions; - QRect cupsPaperRect; - QRect cupsPageRect; QString cupsTempFile; }; diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h index 95ca323c22..337f2250c5 100644 --- a/src/printsupport/kernel/qcups_p.h +++ b/src/printsupport/kernel/qcups_p.h @@ -71,9 +71,6 @@ QT_BEGIN_NAMESPACE // Move back to qcupsprintengine_p.h in the plugin once all usage // removed from the dialogs. #define PPK_CupsOptions QPrintEngine::PrintEnginePropertyKey(0xfe00) -#define PPK_CupsPageRect QPrintEngine::PrintEnginePropertyKey(0xfe01) -#define PPK_CupsPaperRect QPrintEngine::PrintEnginePropertyKey(0xfe02) -#define PPK_CupsStringPageSize QPrintEngine::PrintEnginePropertyKey(0xfe03) Q_DECLARE_TYPEINFO(cups_option_t, Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE); diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp index 2ddfb9c49e..c24905009d 100644 --- a/src/printsupport/kernel/qprintengine_pdf.cpp +++ b/src/printsupport/kernel/qprintengine_pdf.cpp @@ -206,7 +206,7 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->embedFonts = value.toBool(); break; case PPK_Duplex: - d->duplex = static_cast (value.toInt()); + d->duplex = static_cast(value.toInt()); break; case PPK_CustomPaperSize: d->m_pageLayout.setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); @@ -362,7 +362,7 @@ void QPdfPrintEnginePrivate::closePrintDevice() QPdfPrintEnginePrivate::QPdfPrintEnginePrivate(QPrinter::PrinterMode m) : QPdfEnginePrivate(), - duplex(QPrinter::DuplexNone), + duplex(QPrint::DuplexNone), collate(true), copies(1), pageOrder(QPrinter::FirstPageFirst), diff --git a/src/printsupport/kernel/qprintengine_pdf_p.h b/src/printsupport/kernel/qprintengine_pdf_p.h index cc4044d1a0..80d81b4ed3 100644 --- a/src/printsupport/kernel/qprintengine_pdf_p.h +++ b/src/printsupport/kernel/qprintengine_pdf_p.h @@ -68,6 +68,7 @@ #include "private/qpdf_p.h" #include "private/qpaintengine_p.h" #include "qprintengine.h" +#include "qprint_p.h" QT_BEGIN_NAMESPACE @@ -131,7 +132,7 @@ private: QString printProgram; QString selectionOption; - QPrinter::DuplexMode duplex; + QPrint::DuplexMode duplex; bool collate; int copies; QPrinter::PageOrder pageOrder; -- cgit v1.2.3 From c5cbdc2cbce4d2f471836f1a1c7c963ce985ac49 Mon Sep 17 00:00:00 2001 From: John Layt Date: Tue, 21 Jan 2014 20:07:16 +0100 Subject: QPrintEngine - Switch Mac to QPlatformPrintDevice Change the Mac QPrintEngine to use QPlatformPrintDevice and QPageSize for all device and page size related requirements. Change-Id: Ie0e598eceaf1a657a1554c0f56078fd857ef2e06 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 295 +++++++---------------- src/plugins/platforms/cocoa/qprintengine_mac_p.h | 13 +- 2 files changed, 93 insertions(+), 215 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index f34fadd8a1..b63898cd53 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -40,10 +40,10 @@ ****************************************************************************/ #include "qprintengine_mac_p.h" +#include "qcocoaprintersupport.h" #include #include #include -#include #include "qcocoaautoreleasepool.h" @@ -55,6 +55,8 @@ QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(ne { Q_D(QMacPrintEngine); d->mode = mode; + d->m_printDevice = new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId()); + d->m_pageSize = d->m_printDevice->defaultPageSize(); d->initialize(); } @@ -138,126 +140,6 @@ QMacPrintEnginePrivate::~QMacPrintEnginePrivate() delete paintEngine; } -void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps) -{ - Q_Q(QMacPrintEngine); - if (hasCustomPaperSize) { - PMRelease(customPaper); - customPaper = 0; - } - hasCustomPaperSize = (ps == QPrinter::Custom); - PMPrinter printer; - if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { - if (ps != QPrinter::Custom) { - QSizeF newSize = QPageSize(QPageSize::PageSizeId(ps)).size(QPageSize::Millimeter); - QCFType formats; - if (PMSessionCreatePageFormatList(session(), printer, &formats) == noErr) { - CFIndex total = CFArrayGetCount(formats); - PMPageFormat tmp; - PMRect paper; - for (CFIndex idx = 0; idx < total; ++idx) { - tmp = static_cast(const_cast(CFArrayGetValueAtIndex(formats, idx))); - PMGetUnadjustedPaperRect(tmp, &paper); - int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5); - int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5); - if (newSize.width() == wMM && newSize.height() == hMM) { - PMCopyPageFormat(tmp, format()); - // reset the orientation and resolution as they are lost in the copy. - q->setProperty(QPrintEngine::PPK_Orientation, orient); - if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) { - // Don't know, warn for the moment. - qWarning("QMacPrintEngine, problem setting format and resolution for this page size"); - } - break; - } - } - } - } else { - QCFString paperId = QCFString::toCFStringRef(QUuid::createUuid().toString()); - PMPaperMargins paperMargins; - paperMargins.left = leftMargin; - paperMargins.top = topMargin; - paperMargins.right = rightMargin; - paperMargins.bottom = bottomMargin; - PMPaperCreateCustom(printer, paperId, QCFString("Custom size"), customSize.width(), customSize.height(), &paperMargins, &customPaper); - PMPageFormat tmp; - PMCreatePageFormatWithPMPaper(&tmp, customPaper); - PMCopyPageFormat(tmp, format()); - if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) { - // Don't know, warn for the moment. - qWarning("QMacPrintEngine, problem setting paper name"); - } - } - } -} - -QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const -{ - if (hasCustomPaperSize) - return QPrinter::Custom; - PMRect paper; - PMGetUnadjustedPaperRect(format(), &paper); - QSizeF sizef((paper.right - paper.left) / 72.0 * 25.4, (paper.bottom - paper.top) / 72.0 * 25.4); - return QPrinter::PaperSize(QPageSize(sizef, QPageSize::Millimeter).id()); -} - -void QMacPrintEnginePrivate::setPaperName(const QString &name) -{ - Q_Q(QMacPrintEngine); - if (hasCustomPaperSize) { - PMRelease(customPaper); - customPaper = 0; - hasCustomPaperSize = false; - } - PMPrinter printer; - - if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { - CFArrayRef array; - if (PMPrinterGetPaperList(printer, &array) != noErr) - return; - int count = CFArrayGetCount(array); - for (int i = 0; i < count; ++i) { - PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(array, i))); - QCFString paperName; - if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr) { - if (QString(paperName) == name) { - PMPageFormat tmp; - PMCreatePageFormatWithPMPaper(&tmp, paper); - PMCopyPageFormat(tmp, format()); - q->setProperty(QPrintEngine::PPK_Orientation, orient); - if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) { - // Don't know, warn for the moment. - qWarning("QMacPrintEngine, problem setting paper name"); - } - } - } - } - } -} - -QList QMacPrintEnginePrivate::supportedResolutions() const -{ - Q_ASSERT_X(printInfo, "QMacPrinterEngine::supportedResolutions", - "must have a valid printer session"); - UInt32 resCount; - QList resolutions; - PMPrinter printer; - if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { - PMResolution res; - OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount); - if (status == noErr) { - // According to the docs, index start at 1. - for (UInt32 i = 1; i <= resCount; ++i) { - if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr) - resolutions.append(QVariant(int(res.hRes))); - } - } else { - qWarning("QMacPrintEngine::supportedResolutions: Unexpected error: %ld", long(status)); - } - } - return resolutions; -} - QPrinter::PrinterState QMacPrintEngine::printerState() const { return d_func()->state; @@ -413,28 +295,21 @@ void QMacPrintEnginePrivate::initialize() QCocoaAutoReleasePool pool; printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]]; - PMPrinter printer; - if (printInfo && PMSessionGetCurrentPrinter(session(), &printer) == noErr) { - QList resolutions = supportedResolutions(); - if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { - if (resolutions.count() > 1 && mode == QPrinter::HighResolution) { - int max = 0; - for (int i = 0; i < resolutions.count(); ++i) { - int value = resolutions.at(i).toInt(); - if (value > max) - max = value; - } - resolution.hRes = resolution.vRes = max; - } else { - resolution.hRes = resolution.vRes = resolutions.at(0).toInt(); - } - if (resolution.hRes == 0) - resolution.hRes = resolution.vRes = 600; - } else { - resolution.hRes = resolution.vRes = qt_defaultDpi(); - } + QList resolutions = m_printDevice->supportedResolutions(); + if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { + qSort(resolutions); + if (resolutions.count() > 1 && mode == QPrinter::HighResolution) + resolution.hRes = resolution.vRes = resolutions.last(); + else + resolution.hRes = resolution.vRes = resolutions.first(); + if (resolution.hRes == 0) + resolution.hRes = resolution.vRes = 600; + } else { + resolution.hRes = resolution.vRes = qt_defaultDpi(); } + setPageSize(m_pageSize); + QHash::const_iterator propC; for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) { q->setProperty(propC.key(), propC.value()); @@ -445,8 +320,6 @@ void QMacPrintEnginePrivate::releaseSession() { PMSessionEndPageNoDialog(session()); PMSessionEndDocumentNoDialog(session()); - if (hasCustomPaperSize) - PMRelease(customPaper); [printInfo release]; printInfo = 0; } @@ -506,6 +379,35 @@ bool QMacPrintEnginePrivate::newPage_helper() return true; } +void QMacPrintEnginePrivate::setPageSize(const QPageSize &pageSize) +{ + if (!pageSize.isValid()) + return; + + // Get the matching printer paper + QPageSize printerPageSize = m_printDevice->supportedPageSize(pageSize); + if (printerPageSize.isValid()) { + m_pageSize = printerPageSize; + hasCustomPaperSize = false; + } else { + m_pageSize = pageSize; + hasCustomPaperSize = true; + } + if (orient == QPrinter::Landscape) + customSize = m_pageSize.size(QPage::Point).transposed(); + else + customSize = m_pageSize.size(QPage::Point); + + // You cannot set the page size on a PMPageFormat, you must create a new PMPageFormat + PMPageFormat pageFormat; + PMPaper macPaper = m_printDevice->macPaper(pageSize); + PMCreatePageFormatWithPMPaper(&pageFormat, macPaper); + PMSetOrientation(pageFormat, orient == QPrinter::Landscape ? kPMLandscape : kPMPortrait, kPMUnlocked); + PMCopyPageFormat(pageFormat, format()); + if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) + qWarning("QMacPrintEngine: Invalid page format"); + PMRelease(pageFormat); +} void QMacPrintEngine::updateState(const QPaintEngineState &state) { @@ -630,27 +532,19 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va // The following keys are properties and settings that are supported by the Mac PrintEngine case PPK_Resolution: { - PMPrinter printer; - UInt32 count; - if (PMSessionGetCurrentPrinter(d->session(), &printer) != noErr) - break; - if (PMPrinterGetPrinterResolutionCount(printer, &count) != noErr) - break; - PMResolution resolution = { 0.0, 0.0 }; - PMResolution bestResolution = { 0.0, 0.0 }; + // TODO It appears the old code didn't actually set the resolution??? Can we delete all this??? + int bestResolution = 0; int dpi = value.toInt(); int bestDistance = INT_MAX; - for (UInt32 i = 1; i <= count; ++i) { // Yes, it starts at 1 - if (PMPrinterGetIndexedPrinterResolution(printer, i, &resolution) == noErr) { - if (dpi == int(resolution.hRes)) { + foreach (int resolution, d->m_printDevice->supportedResolutions()) { + if (dpi == resolution) { + bestResolution = resolution; + break; + } else { + int distance = qAbs(dpi - resolution); + if (distance < bestDistance) { + bestDistance = distance; bestResolution = resolution; - break; - } else { - int distance = qAbs(dpi - int(resolution.hRes)); - if (distance < bestDistance) { - bestDistance = distance; - bestResolution = resolution; - } } } } @@ -686,47 +580,29 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_OutputFileName: d->outputFilename = value.toString(); break; - case PPK_PaperSize: - d->setPaperSize(QPrinter::PaperSize(value.toInt())); + case PPK_PageSize: + d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt()))); break; case PPK_PaperName: - d->setPaperName(value.toString()); + // Get the named page size from the printer if supported + d->setPageSize(d->m_printDevice->supportedPageSize(value.toString())); break; case PPK_PrinterName: { - bool printerNameSet = false; - OSStatus status = noErr; - QCFType printerList; - status = PMServerCreatePrinterList(kPMServerLocal, &printerList); - if (status == noErr) { - CFIndex count = CFArrayGetCount(printerList); - for (CFIndex i=0; i(const_cast(CFArrayGetValueAtIndex(printerList, i))); - QString name = QCFString::toQString(PMPrinterGetID(printer)); - if (name == value.toString()) { - status = PMSessionSetCurrentPMPrinter(d->session(), printer); - printerNameSet = true; - break; - } - } - } - if (status != noErr) - qWarning("QMacPrintEngine::setPrinterName: Error setting printer: %ld", long(status)); - if (!printerNameSet) { - qWarning("QMacPrintEngine::setPrinterName: Failed to set printer named '%s'.", qPrintable(value.toString())); - d->releaseSession(); - d->state = QPrinter::Idle; - } - break; } - case PPK_CustomPaperSize: - { - PMOrientation orientation; - PMGetOrientation(d->format(), &orientation); - d->customSize = value.toSizeF(); - if (orientation != kPMPortrait) - d->customSize = QSizeF(d->customSize.height(), d->customSize.width()); - d->setPaperSize(QPrinter::Custom); + QString id = value.toString(); + if (id.isEmpty()) + id = QCocoaPrinterSupport().defaultPrintDeviceId(); + else if (!QCocoaPrinterSupport().availablePrintDeviceIds().contains(id)) + break; + d->m_printDevice = new QCocoaPrintDevice(id); + PMPrinter printer = d->m_printDevice->macPrinter(); + PMRetain(printer); + PMSessionSetCurrentPMPrinter(d->session(), printer); + // TODO Do we need to check if the page size, etc, are valid on new printer? break; } + case PPK_CustomPaperSize: + d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); + break; case PPK_PageMargins: { QList margins(value.toList()); @@ -868,11 +744,11 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const } ret = r; break; } - case PPK_PaperSize: - ret = d->paperSize(); + case PPK_PageSize: + ret = d->m_pageSize.id(); break; case PPK_PaperName: - ret = QCFString::toQString([d->printInfo localizedPaperName]); + ret = d->m_pageSize.name(); break; case PPK_PaperRect: { QRect r; @@ -888,23 +764,22 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const } ret = r; break; } - case PPK_PrinterName: { - PMPrinter printer; - OSStatus status = PMSessionGetCurrentPrinter(d->session(), &printer); - if (status != noErr) - qWarning("QMacPrintEngine::printerName: Failed getting current PMPrinter: %ld", long(status)); - if (printer) - ret = QCFString::toQString(PMPrinterGetID(printer)); - break; } + case PPK_PrinterName: + return d->m_printDevice->id(); + break; case PPK_Resolution: { ret = d->resolution.hRes; break; } - case PPK_SupportedResolutions: - ret = d->supportedResolutions(); + case PPK_SupportedResolutions: { + QList list; + foreach (int resolution, d->m_printDevice->supportedResolutions()) + list << resolution; + ret = list; break; + } case PPK_CustomPaperSize: - ret = d->customSize; + return d->m_pageSize.size(QPage::Point); break; case PPK_PageMargins: { diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index e3a8520811..cb68f03fdb 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -60,6 +60,9 @@ #include #include #include +#include + +#include "qcocoaprintdevice.h" #include "qpaintengine_mac_p.h" @@ -122,6 +125,8 @@ public: QPrinter::PrinterMode mode; QPrinter::PrinterState state; QPrinter::Orientation orient; + QSharedDataPointer m_printDevice; + QPageSize m_pageSize; NSPrintInfo *printInfo; PMResolution resolution; QString outputFilename; @@ -136,18 +141,16 @@ public: qreal rightMargin; qreal bottomMargin; QHash valueCache; - PMPaper customPaper; + QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), orient(QPrinter::Portrait), printInfo(0), paintEngine(0), hasCustomPaperSize(false), hasCustomPageMargins(false) {} ~QMacPrintEnginePrivate(); + void initialize(); void releaseSession(); bool newPage_helper(); - void setPaperSize(QPrinter::PaperSize ps); - QPrinter::PaperSize paperSize() const; - void setPaperName(const QString &name); - QList supportedResolutions() const; + void setPageSize(const QPageSize &pageSize); inline bool isPrintSessionInitialized() const { return printInfo != 0; -- cgit v1.2.3 From 4eb36ad5971240a9a934bef7be2c6297e092b797 Mon Sep 17 00:00:00 2001 From: John Layt Date: Thu, 23 Jan 2014 02:06:29 +0100 Subject: QPrintEngine - Switch Mac to QPageLayout Use QPageLayout in the Mac QPaintEngine. Change-Id: I4c160e3875d69879160e289c371c10b1ac028748 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 218 ++++++----------------- src/plugins/platforms/cocoa/qprintengine_mac_p.h | 15 +- src/printsupport/dialogs/qprintdialog_mac.mm | 3 + 3 files changed, 59 insertions(+), 177 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index b63898cd53..bfe44c7ab3 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -44,6 +44,7 @@ #include #include #include +#include #include "qcocoaautoreleasepool.h" @@ -51,12 +52,14 @@ QT_BEGIN_NAMESPACE +extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits); + QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(new QMacPrintEnginePrivate)) { Q_D(QMacPrintEngine); d->mode = mode; d->m_printDevice = new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId()); - d->m_pageSize = d->m_printDevice->defaultPageSize(); + d->m_pageLayout.setPageSize(d->m_printDevice->defaultPageSize()); d->initialize(); } @@ -174,77 +177,22 @@ bool QMacPrintEngine::abort() return ret; } -static inline int qt_get_PDMWidth(PMPageFormat pformat, bool fullPage, - const PMResolution &resolution) -{ - int val = 0; - PMRect r; - qreal hRatio = resolution.hRes / 72; - if (fullPage) { - if (PMGetAdjustedPaperRect(pformat, &r) == noErr) - val = qRound((r.right - r.left) * hRatio); - } else { - if (PMGetAdjustedPageRect(pformat, &r) == noErr) - val = qRound((r.right - r.left) * hRatio); - } - return val; -} - -static inline int qt_get_PDMHeight(PMPageFormat pformat, bool fullPage, - const PMResolution &resolution) -{ - int val = 0; - PMRect r; - qreal vRatio = resolution.vRes / 72; - if (fullPage) { - if (PMGetAdjustedPaperRect(pformat, &r) == noErr) - val = qRound((r.bottom - r.top) * vRatio); - } else { - if (PMGetAdjustedPageRect(pformat, &r) == noErr) - val = qRound((r.bottom - r.top) * vRatio); - } - return val; -} - - int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const { Q_D(const QMacPrintEngine); int val = 1; switch (m) { case QPaintDevice::PdmWidth: - if (d->hasCustomPaperSize) { - val = qRound(d->customSize.width()); - if (d->hasCustomPageMargins) { - val -= qRound(d->leftMargin + d->rightMargin); - } else { - QList margins = property(QPrintEngine::PPK_PageMargins).toList(); - val -= qRound(margins.at(0).toDouble() + margins.at(2).toDouble()); - } - } else { - val = qt_get_PDMWidth(d->format(), property(PPK_FullPage).toBool(), d->resolution); - } + val = d->m_pageLayout.paintRectPixels(d->resolution.hRes).width(); break; case QPaintDevice::PdmHeight: - if (d->hasCustomPaperSize) { - val = qRound(d->customSize.height()); - if (d->hasCustomPageMargins) { - val -= qRound(d->topMargin + d->bottomMargin); - } else { - QList margins = property(QPrintEngine::PPK_PageMargins).toList(); - val -= qRound(margins.at(1).toDouble() + margins.at(3).toDouble()); - } - } else { - val = qt_get_PDMHeight(d->format(), property(PPK_FullPage).toBool(), d->resolution); - } + val = d->m_pageLayout.paintRectPixels(d->resolution.hRes).height(); break; case QPaintDevice::PdmWidthMM: - val = metric(QPaintDevice::PdmWidth); - val = int((val * 254 + 5 * d->resolution.hRes) / (10 * d->resolution.hRes)); + val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).width()); break; case QPaintDevice::PdmHeightMM: - val = metric(QPaintDevice::PdmHeight); - val = int((val * 254 + 5 * d->resolution.vRes) / (10 * d->resolution.vRes)); + val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).height()); break; case QPaintDevice::PdmPhysicalDpiX: case QPaintDevice::PdmPhysicalDpiY: { @@ -290,8 +238,6 @@ void QMacPrintEnginePrivate::initialize() q->gccaps = paintEngine->gccaps; - fullPage = false; - QCocoaAutoReleasePool pool; printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]]; @@ -308,7 +254,7 @@ void QMacPrintEnginePrivate::initialize() resolution.hRes = resolution.vRes = qt_defaultDpi(); } - setPageSize(m_pageSize); + setPageSize(m_pageLayout.pageSize()); QHash::const_iterator propC; for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) { @@ -347,8 +293,8 @@ bool QMacPrintEnginePrivate::newPage_helper() return false; } - QRect page = q->property(QPrintEngine::PPK_PageRect).toRect(); - QRect paper = q->property(QPrintEngine::PPK_PaperRect).toRect(); + QRect page = m_pageLayout.paintRectPixels(resolution.hRes); + QRect paper = m_pageLayout.fullRectPixels(resolution.hRes); CGContextRef cgContext; OSStatus err = noErr; @@ -365,7 +311,7 @@ bool QMacPrintEnginePrivate::newPage_helper() CGContextScaleCTM(cgContext, 1, -1); CGContextTranslateCTM(cgContext, 0, -paper.height()); - if (!fullPage) + if (m_pageLayout.mode() != QPageLayout::FullPageMode) CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y()); cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext); cgEngine->d_func()->setClip(0); @@ -386,23 +332,22 @@ void QMacPrintEnginePrivate::setPageSize(const QPageSize &pageSize) // Get the matching printer paper QPageSize printerPageSize = m_printDevice->supportedPageSize(pageSize); - if (printerPageSize.isValid()) { - m_pageSize = printerPageSize; - hasCustomPaperSize = false; - } else { - m_pageSize = pageSize; - hasCustomPaperSize = true; + QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize; + + // Get the PMPaper and check it is valid + PMPaper macPaper = m_printDevice->macPaper(usePageSize); + if (macPaper == 0) { + qWarning() << "QMacPrintEngine: Invalid PMPaper returned for " << pageSize; + return; } - if (orient == QPrinter::Landscape) - customSize = m_pageSize.size(QPage::Point).transposed(); - else - customSize = m_pageSize.size(QPage::Point); + + QMarginsF printable = m_printDevice->printableMargins(usePageSize, m_pageLayout.orientation(), resolution.hRes); + m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units())); // You cannot set the page size on a PMPageFormat, you must create a new PMPageFormat PMPageFormat pageFormat; - PMPaper macPaper = m_printDevice->macPaper(pageSize); PMCreatePageFormatWithPMPaper(&pageFormat, macPaper); - PMSetOrientation(pageFormat, orient == QPrinter::Landscape ? kPMLandscape : kPMPortrait, kPMUnlocked); + PMSetOrientation(pageFormat, m_pageLayout.orientation() == QPageLayout::Landscape ? kPMLandscape : kPMPortrait, kPMUnlocked); PMCopyPageFormat(pageFormat, format()); if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) qWarning("QMacPrintEngine: Invalid page format"); @@ -561,20 +506,23 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString())); break; case PPK_FullPage: - d->fullPage = value.toBool(); + if (value.toBool()) + d->m_pageLayout.setMode(QPageLayout::FullPageMode); + else + d->m_pageLayout.setMode(QPageLayout::StandardMode); break; case PPK_CopyCount: // fallthrough case PPK_NumberOfCopies: PMSetCopies(d->settings(), value.toInt(), false); break; case PPK_Orientation: { - QPrinter::Orientation newOrientation = QPrinter::Orientation(value.toInt()); - if (d->hasCustomPaperSize && (d->orient != newOrientation)) - d->customSize = QSizeF(d->customSize.height(), d->customSize.width()); - d->orient = newOrientation; - PMOrientation o = d->orient == QPrinter::Portrait ? kPMPortrait : kPMLandscape; - PMSetOrientation(d->format(), o, false); + // First try set the Mac format orientation, then set our orientation to match result + QPageLayout::Orientation newOrientation = QPageLayout::Orientation(value.toInt()); + PMOrientation macOrientation = (newOrientation == QPageLayout::Landscape) ? kPMLandscape : kPMPortrait; + PMSetOrientation(d->format(), macOrientation, kPMUnlocked); PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); + PMGetOrientation(d->format(), &macOrientation); + d->m_pageLayout.setOrientation(macOrientation == kPMLandscape ? QPageLayout::Landscape : QPageLayout::Portrait); break; } case PPK_OutputFileName: @@ -607,11 +555,8 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va { QList margins(value.toList()); Q_ASSERT(margins.size() == 4); - d->leftMargin = margins.at(0).toDouble(); - d->topMargin = margins.at(1).toDouble(); - d->rightMargin = margins.at(2).toDouble(); - d->bottomMargin = margins.at(3).toDouble(); - d->hasCustomPageMargins = true; + d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(), + margins.at(2).toReal(), margins.at(3).toReal())); break; } // No default so that compiler will complain if new keys added and not handled in this engine @@ -685,7 +630,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const break; } case PPK_FullPage: - ret = d->fullPage; + ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode; break; case PPK_NumberOfCopies: ret = 1; @@ -700,70 +645,25 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const ret = true; break; case PPK_Orientation: - PMOrientation orientation; - PMGetOrientation(d->format(), &orientation); - ret = orientation == kPMPortrait ? QPrinter::Portrait : QPrinter::Landscape; + ret = d->m_pageLayout.orientation(); break; case PPK_OutputFileName: ret = d->outputFilename; break; - case PPK_PageRect: { + case PPK_PageRect: // PageRect is returned in device pixels - QRect r; - PMRect macrect, macpaper; - qreal hRatio = d->resolution.hRes / 72; - qreal vRatio = d->resolution.vRes / 72; - if (d->hasCustomPaperSize) { - r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio)); - if (d->hasCustomPageMargins) { - r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), - -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio)); - } else { - QList margins = property(QPrintEngine::PPK_PageMargins).toList(); - r.adjust(qRound(margins.at(0).toDouble() * hRatio), - qRound(margins.at(1).toDouble() * vRatio), - -qRound(margins.at(2).toDouble() * hRatio), - -qRound(margins.at(3).toDouble()) * vRatio); - } - } else if (PMGetAdjustedPageRect(d->format(), ¯ect) == noErr - && PMGetAdjustedPaperRect(d->format(), &macpaper) == noErr) - { - if (d->fullPage || d->hasCustomPageMargins) { - r.setCoords(int(macpaper.left * hRatio), int(macpaper.top * vRatio), - int(macpaper.right * hRatio), int(macpaper.bottom * vRatio)); - r.translate(-r.x(), -r.y()); - if (d->hasCustomPageMargins) { - r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), - -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio)); - } - } else { - r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio), - int(macrect.right * hRatio), int(macrect.bottom * vRatio)); - r.translate(int(-macpaper.left * hRatio), int(-macpaper.top * vRatio)); - } - } - ret = r; - break; } + ret = d->m_pageLayout.paintRectPixels(d->resolution.hRes); + break; case PPK_PageSize: - ret = d->m_pageSize.id(); + ret = d->m_pageLayout.pageSize().id(); break; case PPK_PaperName: - ret = d->m_pageSize.name(); - break; - case PPK_PaperRect: { - QRect r; - PMRect macrect; - qreal hRatio = d->resolution.hRes / 72; - qreal vRatio = d->resolution.vRes / 72; - if (d->hasCustomPaperSize) { - r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio)); - } else if (PMGetAdjustedPaperRect(d->format(), ¯ect) == noErr) { - r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio), - int(macrect.right * hRatio), int(macrect.bottom * vRatio)); - r.translate(-r.x(), -r.y()); - } - ret = r; - break; } + ret = d->m_pageLayout.pageSize().name(); + break; + case PPK_PaperRect: + // PaperRect is returned in device pixels + ret = d->m_pageLayout.fullRectPixels(d->resolution.hRes); + break; case PPK_PrinterName: return d->m_printDevice->id(); break; @@ -779,25 +679,13 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const break; } case PPK_CustomPaperSize: - return d->m_pageSize.size(QPage::Point); + ret = d->m_pageLayout.fullRectPoints().size(); break; - case PPK_PageMargins: - { - QList margins; - if (d->hasCustomPageMargins) { - margins << d->leftMargin << d->topMargin - << d->rightMargin << d->bottomMargin; - } else if (!d->hasCustomPaperSize) { - PMPaperMargins paperMargins; - PMPaper paper; - PMGetPageFormatPaper(d->format(), &paper); - PMPaperGetMargins(paper, &paperMargins); - margins << paperMargins.left << paperMargins.top - << paperMargins.right << paperMargins.bottom; - } else { - margins << 0 << 0 << 0 << 0; - } - ret = margins; + case PPK_PageMargins: { + QList list; + QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point); + list << margins.left() << margins.top() << margins.right() << margins.bottom(); + ret = list; break; } // No default so that compiler will complain if new keys added and not handled in this engine diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index cb68f03fdb..12a87b35e9 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -124,27 +124,18 @@ class QMacPrintEnginePrivate : public QPaintEnginePrivate public: QPrinter::PrinterMode mode; QPrinter::PrinterState state; - QPrinter::Orientation orient; QSharedDataPointer m_printDevice; - QPageSize m_pageSize; + QPageLayout m_pageLayout; NSPrintInfo *printInfo; PMResolution resolution; QString outputFilename; QString m_creator; - bool fullPage; QPaintEngine *paintEngine; - bool hasCustomPaperSize; - QSizeF customSize; - bool hasCustomPageMargins; - qreal leftMargin; - qreal topMargin; - qreal rightMargin; - qreal bottomMargin; QHash valueCache; QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), - orient(QPrinter::Portrait), printInfo(0), paintEngine(0), - hasCustomPaperSize(false), hasCustomPageMargins(false) {} + m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))), + printInfo(0), paintEngine(0) {} ~QMacPrintEnginePrivate(); void initialize(); diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index bf1617065b..67216f7f2a 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -49,9 +49,12 @@ #include #include #include +#include #ifndef QT_NO_PRINTDIALOG +extern qreal qt_pointMultiplier(QPageLayout::Unit unit); + QT_BEGIN_NAMESPACE class QPrintDialogPrivate : public QAbstractPrintDialogPrivate -- cgit v1.2.3 From ab42391cd0b4cb0be03d0083f4e0d2b039a85a19 Mon Sep 17 00:00:00 2001 From: John Layt Date: Mon, 20 Jan 2014 17:59:57 +0100 Subject: QPrintEngine - Switch Windows to QPlatformPrintDevice Change the Windows QPrintEngine implementation to use the QPlatformPrintDevice to obtain device information, and use QPageSize to obtain page size conversions. A following change will use QPageLayout to store that page size. Change-Id: I990943e2b62ab6dab2c4d4a292c7ed7261beadf2 Reviewed-by: Lars Knoll --- src/printsupport/kernel/qprintengine_win.cpp | 531 ++++++++------------------- src/printsupport/kernel/qprintengine_win_p.h | 29 +- src/printsupport/kernel/qprinter.cpp | 14 +- 3 files changed, 170 insertions(+), 404 deletions(-) (limited to 'src') diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index c5f5057b14..6aec4919fd 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -50,6 +50,9 @@ #include #include +#include +#include + #include #include #include @@ -67,164 +70,12 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); extern QPainterPath qt_regionToPath(const QRegion ®ion); -Q_PRINTSUPPORT_EXPORT QSizeF qt_SizeFromUnitToMillimeter(const QSizeF &, QPrinter::Unit, double); -Q_PRINTSUPPORT_EXPORT double qt_multiplierForUnit(QPrinter::Unit unit, int resolution); // #define QT_DEBUG_DRAW static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc, bool convertToText, const QTransform &xform, const QPointF &topLeft); -static const struct { - int winSizeName; - QPrinter::PaperSize qtSizeName; -} dmMapping[] = { - { DMPAPER_LETTER, QPrinter::Letter }, - { DMPAPER_LETTERSMALL, QPrinter::Letter }, - { DMPAPER_TABLOID, QPrinter::Tabloid }, - { DMPAPER_LEDGER, QPrinter::Ledger }, - { DMPAPER_LEGAL, QPrinter::Legal }, - { DMPAPER_EXECUTIVE, QPrinter::Executive }, - { DMPAPER_A3, QPrinter::A3 }, - { DMPAPER_A4, QPrinter::A4 }, - { DMPAPER_A4SMALL, QPrinter::A4 }, - { DMPAPER_A5, QPrinter::A5 }, - { DMPAPER_B4, QPrinter::B4 }, - { DMPAPER_B5, QPrinter::B5 }, - { DMPAPER_A4_PLUS, QPrinter::Folio }, - { DMPAPER_ENV_10, QPrinter::Comm10E }, - { DMPAPER_ENV_DL, QPrinter::DLE }, - { DMPAPER_ENV_C3, QPrinter::C5E }, - { DMPAPER_LETTER_EXTRA, QPrinter::Letter }, - { DMPAPER_LEGAL_EXTRA, QPrinter::Legal }, - { DMPAPER_TABLOID_EXTRA, QPrinter::Tabloid }, - { DMPAPER_A4_EXTRA, QPrinter::A4}, - { DMPAPER_LETTER_TRANSVERSE, QPrinter::Letter}, - { DMPAPER_A4_TRANSVERSE, QPrinter::A4}, - { DMPAPER_LETTER_EXTRA_TRANSVERSE, QPrinter::Letter }, - { DMPAPER_A_PLUS, QPrinter::A4 }, - { DMPAPER_B_PLUS, QPrinter::A3 }, - { DMPAPER_LETTER_PLUS, QPrinter::Letter }, - { DMPAPER_A5_TRANSVERSE, QPrinter::A5 }, - { DMPAPER_B5_TRANSVERSE, QPrinter::B5 }, - { DMPAPER_A3_EXTRA, QPrinter::A3 }, - { DMPAPER_A5_EXTRA, QPrinter::A5 }, - { DMPAPER_B5_EXTRA, QPrinter::B5 }, - { DMPAPER_A2, QPrinter::A2 }, - { DMPAPER_A3_TRANSVERSE, QPrinter::A3 }, - { DMPAPER_A3_EXTRA_TRANSVERSE,QPrinter::A3 }, - { 0, QPrinter::Custom } -}; - -// Return a list of printer paper sizes in millimeters with the corresponding dmPaperSize value -static QList > printerPaperSizes(const QString &printerName) -{ - QList > result; - const wchar_t *name = reinterpret_cast(printerName.utf16()); - DWORD paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERS, NULL, NULL); - if ((int)paperNameCount > 0) { - // If they are not equal, then there seems to be a problem with the driver - if (paperNameCount != DeviceCapabilities(name, NULL, DC_PAPERSIZE, NULL, NULL)) - return result; - QScopedArrayPointer papersNames(new wchar_t[paperNameCount]); - paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERS, papersNames.data(), NULL); - result.reserve(paperNameCount); - QScopedArrayPointer paperSizes(new POINT[paperNameCount]); - paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERSIZE, (wchar_t *)paperSizes.data(), NULL); - for (int i=0; i <(int)paperNameCount; i++) - result.push_back(qMakePair(QSizeF(paperSizes[i].x / 10, paperSizes[i].y / 10), papersNames[i])); - } - return result; -} - -// Find the best-matching printer paper for size in millimeters. -static inline int findCustomPaperSize(const QSizeF &needlePt, const QString &printerName) -{ - const QList > sizes = printerPaperSizes(printerName); - const qreal nw = needlePt.width(); - const qreal nh = needlePt.height(); - for (int i = 0; i < sizes.size(); ++i) { - if (qAbs(nw - sizes.at(i).first.width()) <= 1 && qAbs(nh - sizes.at(i).first.height()) <= 1) - return sizes.at(i).second; - } - return -1; -} - -static inline void setDevModePaperFlags(DEVMODE *devMode, bool custom) -{ - if (custom) { - devMode->dmPaperSize = DMPAPER_USER; - devMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH; - } else { - devMode->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH); - devMode->dmPaperLength = 0; - devMode->dmPaperWidth = 0; - } -} - -QPrinter::PaperSize mapDevmodePaperSize(int s) -{ - int i = 0; - while ((dmMapping[i].winSizeName > 0) && (dmMapping[i].winSizeName != s)) - i++; - return dmMapping[i].qtSizeName; -} - -static int mapPaperSizeDevmode(QPrinter::PaperSize s) -{ - int i = 0; - while ((dmMapping[i].winSizeName > 0) && (dmMapping[i].qtSizeName != s)) - i++; - return dmMapping[i].winSizeName; -} - -static const struct { - int winSourceName; - QPrinter::PaperSource qtSourceName; -} sources[] = { - { DMBIN_UPPER, QPrinter::Upper }, // = DBMIN_ONLYONE - { DMBIN_LOWER, QPrinter::Lower }, - { DMBIN_MIDDLE, QPrinter::Middle }, - { DMBIN_MANUAL, QPrinter::Manual }, - { DMBIN_ENVELOPE, QPrinter::Envelope }, - { DMBIN_ENVMANUAL, QPrinter::EnvelopeManual }, - { DMBIN_AUTO, QPrinter::Auto }, - { DMBIN_TRACTOR, QPrinter::Tractor }, - { DMBIN_SMALLFMT, QPrinter::SmallFormat }, - { DMBIN_LARGEFMT, QPrinter::LargeFormat }, - { DMBIN_LARGECAPACITY, QPrinter::LargeCapacity }, - { DMBIN_CASSETTE, QPrinter::Cassette }, - { DMBIN_FORMSOURCE, QPrinter::FormSource }, - { DMBIN_USER, QPrinter::CustomSource }, - { 0, (QPrinter::PaperSource) -1 } -}; - -static QPrinter::PaperSource mapDevmodePaperSource(int s) -{ - int i = 0; - while ((sources[i].winSourceName > 0) && (sources[i].winSourceName != s)) - i++; - return sources[i].winSourceName ? sources[i].qtSourceName : (QPrinter::PaperSource) s; -} - -static int mapPaperSourceDevmode(QPrinter::PaperSource s) -{ - int i = 0; - while ((sources[i].qtSourceName >= 0) && (sources[i].qtSourceName != s)) - i++; - return sources[i].winSourceName ? sources[i].winSourceName : s; -} - -static inline uint qwcsnlen(const wchar_t *str, uint maxlen) -{ - uint length = 0; - if (str) { - while (length < maxlen && *str++) - length++; - } - return length; -} - QWin32PrintEngine::QWin32PrintEngine(QPrinter::PrinterMode mode) : QAlphaPaintEngine(*(new QWin32PrintEnginePrivate), PaintEngineFeatures(PrimitiveTransform @@ -236,7 +87,10 @@ QWin32PrintEngine::QWin32PrintEngine(QPrinter::PrinterMode mode) { Q_D(QWin32PrintEngine); d->mode = mode; - d->queryDefault(); + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) + d->m_printDevice = ps->createDefaultPrintDevice(); + d->m_pageSize = d->m_printDevice.defaultPageSize(); d->initialize(); } @@ -1035,11 +889,6 @@ void QWin32PrintEngine::drawPolygon(const QPointF *points, int pointCount, Polyg d->has_brush = has_brush; } -void QWin32PrintEnginePrivate::queryDefault() -{ - QWin32PrintEngine::queryDefaultPrinter(name); -} - QWin32PrintEnginePrivate::~QWin32PrintEnginePrivate() { if (hdc) @@ -1055,12 +904,12 @@ void QWin32PrintEnginePrivate::initialize() Q_ASSERT(!devMode); Q_ASSERT(!pInfo); - if (name.isEmpty()) + if (!m_printDevice.isValid()) return; txop = QTransform::TxNone; - bool ok = OpenPrinter((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0); + bool ok = OpenPrinter((LPWSTR)m_printDevice.id().utf16(), (LPHANDLE)&hPrinter, 0); if (!ok) { qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed"); return; @@ -1086,7 +935,7 @@ void QWin32PrintEnginePrivate::initialize() } devMode = pInfo->pDevMode; - hdc = CreateDC(NULL, reinterpret_cast(name.utf16()), 0, devMode); + hdc = CreateDC(NULL, reinterpret_cast(m_printDevice.id().utf16()), 0, devMode); Q_ASSERT(hPrinter); Q_ASSERT(pInfo); @@ -1094,6 +943,7 @@ void QWin32PrintEnginePrivate::initialize() if (devMode) { num_copies = devMode->dmCopies; devMode->dmCollate = DMCOLLATE_TRUE; + updatePageSize(); } initHDC(); @@ -1208,31 +1058,6 @@ void QWin32PrintEnginePrivate::release() devMode = 0; } -QList QWin32PrintEnginePrivate::queryResolutions() const -{ - // Read the supported resolutions of the printer. - QList list; - - DWORD numRes = DeviceCapabilities(reinterpret_cast(name.utf16()), NULL, - DC_ENUMRESOLUTIONS, 0, 0); - if (numRes == (DWORD)-1) - return list; - - LONG *enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); - DWORD errRes = DeviceCapabilities(reinterpret_cast(name.utf16()), NULL, - DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0); - - if (errRes == (DWORD)-1) { - qErrnoWarning("QWin32PrintEngine::queryResolutions: DeviceCapabilities failed"); - return list; - } - - for (uint i=0; idevMode) break; - d->devMode->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); - d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom); - setDevModePaperFlags(d->devMode, d->has_custom_paper_size); - d->doReinit(); + const QPageSize pageSize = QPageSize(QPageSize::PageSizeId(value.toInt())); + if (pageSize.isValid()) { + d->setPageSize(pageSize); + d->doReinit(); + } break; + } - case PPK_PaperName: - { - if (!d->devMode) - break; - const wchar_t *name = reinterpret_cast(d->name.utf16()); - DWORD size = DeviceCapabilities(name, NULL, DC_PAPERNAMES, NULL, NULL); - if ((int)size > 0) { - QScopedArrayPointer paperNames(new wchar_t[size*64]); - if (size != DeviceCapabilities(name, NULL, DC_PAPERNAMES, paperNames.data(), NULL)) - break; - int paperPos = -1; - for (int i = 0; i < (int)size; ++i) { - wchar_t *copyOfPaper = paperNames.data() + (i * 64); - if (value.toString() == QString::fromWCharArray(copyOfPaper, qwcsnlen(copyOfPaper, 64))) { - paperPos = i; - break; - } - } - size = DeviceCapabilities(name, NULL, DC_PAPERS, NULL, NULL); - if ((int)size > 0) { - QScopedArrayPointer papers(new wchar_t[size]); - size = DeviceCapabilities(name, NULL, DC_PAPERS, papers.data(), NULL); - QScopedArrayPointer paperSizes(new POINT[size]); - DWORD paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERSIZE, (wchar_t *)paperSizes.data(), NULL); - if (paperNameCount == size) { - const double multiplier = qt_multiplierForUnit(QPrinter::Millimeter, d->resolution); - d->paper_size = QSizeF((paperSizes[paperPos].x / 10.0) * multiplier, (paperSizes[paperPos].y / 10.0) * multiplier); - // Our sizes may not match the paper name's size exactly - // So we treat it as custom so we know the paper size is correct - d->has_custom_paper_size = true; - d->devMode->dmPaperSize = papers[paperPos]; - setDevModePaperFlags(d->devMode, false); - d->doReinit(); - } - } - } + case PPK_PaperName: { + if (!d->devMode) + break; + // Get the named page size from the printer if supported + const QPageSize pageSize = d->m_printDevice.supportedPageSize(value.toString()); + if (pageSize.isValid()) { + d->setPageSize(pageSize); + d->doReinit(); } break; - case PPK_PaperSource: - { - if (!d->devMode) - break; - int dmMapped = DMBIN_AUTO; - - QList v = property(PPK_PaperSources).toList(); - if (v.contains(value)) - dmMapped = mapPaperSourceDevmode(QPrinter::PaperSource(value.toInt())); + } - d->devMode->dmDefaultSource = dmMapped; - d->doReinit(); + case PPK_PaperSource: { + if (!d->devMode) + break; + QPrint::InputSlotId inputSlotId = QPrint::InputSlotId(value.toInt()); + foreach (const QPrint::InputSlot &inputSlot, d->m_printDevice.supportedInputSlots()) { + if (inputSlot.id == inputSlotId) { + d->devMode->dmDefaultSource = inputSlot.windowsId; + d->doReinit(); + break; + } } break; + } - case PPK_PrinterName: - d->name = value.toString(); - if (d->name.isEmpty()) - d->queryDefault(); - d->initialize(); + case PPK_PrinterName: { + QString id = value.toString(); + const QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return; + QPrintDevice printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id); + if (printDevice.isValid()) { + d->m_printDevice = printDevice; + // TODO Do we need to check if the page size is valid on new printer? + d->initialize(); + } break; + } case PPK_Resolution: { @@ -1442,33 +1249,26 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & } break; - case PPK_WindowsPageSize: + case PPK_WindowsPageSize: { if (!d->devMode) break; - d->has_custom_paper_size = false; - d->devMode->dmPaperSize = value.toInt(); - setDevModePaperFlags(d->devMode, d->has_custom_paper_size); - d->doReinit(); + const QPageSize pageSize = QPageSize(QPageSize::id(value.toInt())); + if (pageSize.isValid()) { + d->setPageSize(pageSize); + d->doReinit(); + break; + } break; + } - case PPK_CustomPaperSize: - { - d->has_custom_paper_size = true; - d->paper_size = value.toSizeF(); + case PPK_CustomPaperSize: { if (!d->devMode) break; - const QSizeF sizeMM = qt_SizeFromUnitToMillimeter(d->paper_size, QPrinter::Point, d->resolution); - const int match = findCustomPaperSize(sizeMM, d->name); - setDevModePaperFlags(d->devMode, (match >= 0) ? false : true); - if (match >= 0) { - d->devMode->dmPaperSize = match; - if (d->devMode->dmOrientation != DMORIENT_PORTRAIT) - qSwap(d->paper_size.rwidth(), d->paper_size.rheight()); - } else { - d->devMode->dmPaperLength = qRound(sizeMM.height() * 10.0); - d->devMode->dmPaperWidth = qRound(sizeMM.width() * 10.0); + const QPageSize pageSize = QPageSize(value.toSizeF(), QPageSize::Point); + if (pageSize.isValid()) { + d->setPageSize(pageSize); + d->doReinit(); } - d->doReinit(); break; } @@ -1587,16 +1387,8 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const } break; - case PPK_PaperSize: - if (d->has_custom_paper_size) { - value = QPrinter::Custom; - } else { - if (!d->devMode) { - value = QPrinter::A4; - } else { - value = mapDevmodePaperSize(d->devMode->dmPaperSize); - } - } + case PPK_PageSize: + value = d->m_pageSize.id(); break; case PPK_PaperRect: @@ -1610,88 +1402,57 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_PaperName: - if (!d->devMode) { - value = QLatin1String("A4"); - } else { - const wchar_t *name = reinterpret_cast(d->name.utf16()); - DWORD size = DeviceCapabilities(name, NULL, DC_PAPERS, NULL, NULL); - int paperSizePos = -1; - if ((int)size > 0) { - QScopedArrayPointer papers(new wchar_t[size]); - if (size != DeviceCapabilities(name, NULL, DC_PAPERS, papers.data(), NULL)) - break; - for (int i=0;i<(int)size;i++) { - if (papers[i] == d->devMode->dmPaperSize) { - paperSizePos = i; - break; - } - } - } - if (paperSizePos != -1) { - size = DeviceCapabilities(name, NULL, DC_PAPERNAMES, NULL, NULL); - if ((int)size > 0) { - QScopedArrayPointer paperNames(new wchar_t[size*64]); - size = DeviceCapabilities(name, NULL, DC_PAPERNAMES, paperNames.data(), NULL); - wchar_t *copyOfPaper = paperNames.data() + (paperSizePos * 64); - value = QString::fromWCharArray(copyOfPaper, qwcsnlen(copyOfPaper, 64)); - } - } - } + value = d->m_pageSize.name(); break; case PPK_PaperSource: if (!d->devMode) { - value = QPrinter::Auto; + value = d->m_printDevice.defaultInputSlot().id; } else { - value = mapDevmodePaperSource(d->devMode->dmDefaultSource); + value = QPrint::Auto; + foreach (const QPrint::InputSlot inputSlot, d->m_printDevice.supportedInputSlots()) { + if (inputSlot.windowsId == d->devMode->dmDefaultSource) { + value = inputSlot.id; + break; + } + } } break; case PPK_PrinterName: - value = d->name; + value = d->m_printDevice.id(); break; case PPK_Resolution: - if (d->resolution || !d->name.isEmpty()) + if (d->resolution || d->m_printDevice.isValid()) value = d->resolution; break; - case PPK_SupportedResolutions: - value = d->queryResolutions(); + case PPK_SupportedResolutions: { + QList list; + foreach (int resolution, d->m_printDevice.supportedResolutions()) + list << resolution; + value = list; break; + } case PPK_WindowsPageSize: - if (!d->devMode) { - value = -1; - } else { - value = d->devMode->dmPaperSize; - } + value = d->m_pageSize.windowsId(); break; - case PPK_PaperSources: - { - int available = DeviceCapabilities((const wchar_t *)d->name.utf16(), NULL, DC_BINS, 0, d->devMode); - - if (available <= 0) - break; - - wchar_t *data = new wchar_t[available]; - int count = DeviceCapabilities((const wchar_t *)d->name.utf16(), NULL, DC_BINS, data, d->devMode); - - QList out; - for (int i=0; i out; + foreach (const QPrint::InputSlot inputSlot, d->m_printDevice.supportedInputSlots()) + out << inputSlot.id; + value = out; break; + } case PPK_CustomPaperSize: - value = d->paper_size; + if (property(PPK_Orientation) == QPrinter::Landscape) + value = d->m_pageSize.sizePoints().transposed(); + else + value = d->m_pageSize.sizePoints(); break; case PPK_PageMargins: @@ -1733,33 +1494,11 @@ void QWin32PrintEngine::releaseDC(HDC) const } -void QWin32PrintEngine::queryDefaultPrinter(QString &name) -{ - /* Read the default printer name, driver and port with the intuitive function - * Strings "windows" and "device" are specified in the MSDN under EnumPrinters() - */ - QString noPrinters(QLatin1String("qt_no_printers")); - wchar_t buffer[256]; - GetProfileString(L"windows", L"device", - reinterpret_cast(noPrinters.utf16()), - buffer, 256); - QString output = QString::fromWCharArray(buffer); - if (output.isEmpty() || output == noPrinters) // no printers - return; - - QStringList info = output.split(QLatin1Char(',')); - int infoSize = info.size(); - if (infoSize > 0) { - if (name.isEmpty()) - name = info.at(0); - } -} - HGLOBAL *QWin32PrintEngine::createGlobalDevNames() { Q_D(QWin32PrintEngine); - int size = sizeof(DEVNAMES) + d->name.length() * 2 + 2; + int size = sizeof(DEVNAMES) + d->m_printDevice.id().length() * 2 + 2; HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); @@ -1767,7 +1506,7 @@ HGLOBAL *QWin32PrintEngine::createGlobalDevNames() dn->wDeviceOffset = sizeof(DEVNAMES) / sizeof(wchar_t); dn->wOutputOffset = 0; - memcpy((ushort*)dn + dn->wDeviceOffset, d->name.utf16(), d->name.length() * 2 + 2); + memcpy((ushort*)dn + dn->wDeviceOffset, d->m_printDevice.id().utf16(), d->m_printDevice.id().length() * 2 + 2); dn->wDefault = 0; GlobalUnlock(hGlobal); @@ -1779,7 +1518,10 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD Q_D(QWin32PrintEngine); if (globalDevNames) { DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevNames); - d->name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); + QString id = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) + d->m_printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id); GlobalUnlock(globalDevNames); } @@ -1788,12 +1530,12 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD d->release(); d->globalDevMode = globalDevMode; d->devMode = dm; - d->hdc = CreateDC(NULL, reinterpret_cast(d->name.utf16()), 0, dm); + d->hdc = CreateDC(NULL, reinterpret_cast(d->m_printDevice.id().utf16()), 0, dm); d->num_copies = d->devMode->dmCopies; - d->updateCustomPaperSize(); + d->updatePageSize(); - if (!OpenPrinter((wchar_t*)d->name.utf16(), &d->hPrinter, 0)) + if (!OpenPrinter((wchar_t*)d->m_printDevice.id().utf16(), &d->hPrinter, 0)) qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); } @@ -1807,6 +1549,54 @@ HGLOBAL QWin32PrintEngine::globalDevMode() return d->globalDevMode; } + +void QWin32PrintEnginePrivate::setPageSize(const QPageSize &pageSize) +{ + if (!pageSize.isValid()) + return; + + // Use the printer page size if supported + QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize); + m_pageSize = printerPageSize.isValid() ? printerPageSize : pageSize; + + if (devMode->dmOrientation == DMORIENT_LANDSCAPE) + paper_size = pageSize.size(QPage::Point).transposed(); + else + paper_size = pageSize.size(QPage::Point); + + // Setup if Windows custom size, i.e. not a known Windows ID + if (printerPageSize.isValid()) { + has_custom_paper_size = false; + devMode->dmPaperSize = m_pageSize.windowsId(); + devMode->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH); + devMode->dmPaperWidth = 0; + devMode->dmPaperLength = 0; + } else { + has_custom_paper_size = true; + devMode->dmPaperSize = DMPAPER_USER; + devMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH; + // Size in tenths of a millimeter + const QSizeF sizeMM = m_pageSize.size(QPage::Millimeter); + devMode->dmPaperWidth = qRound(sizeMM.width() * 10.0); + devMode->dmPaperLength = qRound(sizeMM.height() * 10.0); + } +} + +// Called by print dialogs after devMode updated with new page size +// Know devMode->dmPaperSize is valid, refresh QPageSize to match +void QWin32PrintEnginePrivate::updatePageSize() +{ + if (devMode->dmPaperSize >= DMPAPER_USER) { + // Is a custom size + QPageSize pageSize = QPageSize(QSizeF(devMode->dmPaperWidth / 10.0f, devMode->dmPaperLength / 10.0f), + QPage::Millimeter); + setPageSize(pageSize); + } else { + // Is a supported size + setPageSize(QPageSize(QPageSize::id(devMode->dmPaperSize))); + } +} + static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc, bool convertToText, const QTransform &xform, const QPointF &topLeft) { @@ -1922,27 +1712,6 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h SelectObject(hdc, old_font); } -void QWin32PrintEnginePrivate::updateCustomPaperSize() -{ - const uint paperSize = devMode->dmPaperSize; - const double multiplier = qt_multiplierForUnit(QPrinter::Millimeter, resolution); - has_custom_paper_size = false; - if (paperSize == DMPAPER_USER) { - has_custom_paper_size = true; - paper_size = QSizeF((devMode->dmPaperWidth / 10.0) * multiplier, (devMode->dmPaperLength / 10.0) * multiplier); - } else if (mapDevmodePaperSize(paperSize) == QPrinter::Custom) { - has_custom_paper_size = true; - const QList > paperSizes = printerPaperSizes(name); - for (int i=0; i +#include #include #include -#include #include +#include #include QT_BEGIN_NAMESPACE @@ -105,7 +106,10 @@ public: HDC getDC() const; void releaseDC(HDC) const; - static void queryDefaultPrinter(QString &name); + /* Used by print/page setup dialogs */ + void setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode); + HGLOBAL *createGlobalDevNames(); + HGLOBAL globalDevMode(); private: friend class QPrintDialog; @@ -137,10 +141,6 @@ public: ~QWin32PrintEnginePrivate(); - /* Reads the default printer name and its driver (printerProgram) into - the engines private data. */ - void queryDefault(); - /* Initializes the printer data based on the current printer name. This function creates a DEVMODE struct, HDC and a printer handle. If these structures are already in use, they are freed using release @@ -155,10 +155,6 @@ public: etc and resets the corresponding members to 0. */ void release(); - /* Queries the resolutions for the current printer, and returns them - in a list. */ - QList queryResolutions() const; - /* Resets the DC with changes in devmode. If the printer is active this function only sets the reinit variable to true so it is handled in the next begin or newpage. */ @@ -176,12 +172,14 @@ public: void fillPath_dev(const QPainterPath &path, const QColor &color); void strokePath_dev(const QPainterPath &path, const QColor &color, qreal width); + void setPageSize(const QPageSize &pageSize); + void updatePageSize(); + void updateOrigin(); void initDevRects(); void setPageMargins(int margin_left, int margin_top, int margin_right, int margin_bottom); QRect getPageMargins() const; - void updateCustomPaperSize(); // Windows GDI printer references. HANDLE hPrinter; @@ -195,8 +193,8 @@ public: QPrinter::PrinterMode mode; - // Printer info - QString name; + // Print Device + QPrintDevice m_printDevice; // Document info QString docName; @@ -206,6 +204,9 @@ public: QPrinter::PrinterState state; int resolution; + // Page Layout + QPageSize m_pageSize; + // This QRect is used to store the exact values // entered into the PageSetup Dialog because those are // entered in mm but are since converted to device coordinates. @@ -243,7 +244,7 @@ public: QColor brush_color; QPen pen; QColor pen_color; - QSizeF paper_size; + QSizeF paper_size; // In points QTransform painterMatrix; QTransform matrix; diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 878dac60d5..9e10f5c636 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -151,15 +151,11 @@ Q_PRINTSUPPORT_EXPORT QSizeF qt_printerPaperSize(QPrinter::Orientation orientati QPrinter::Unit unit, int resolution) { - int width_index = 0; - int height_index = 1; - if (orientation == QPrinter::Landscape) { - width_index = 1; - height_index = 0; - } - const qreal multiplier = qt_multiplierForUnit(unit, resolution); - return QSizeF((qt_paperSizes[paperSize][width_index] * 72 / 25.4) / multiplier, - (qt_paperSizes[paperSize][height_index] * 72 / 25.4) / multiplier); + QPageSize pageSize = QPageSize(QPageSize::PageSizeId(paperSize)); + if (orientation == QPrinter::Landscape) + return pageSize.size(QPage::Unit(unit), resolution).transposed(); + else + return pageSize.size(QPage::Unit(unit), resolution); } QPrinterInfo QPrinterPrivate::findValidPrinter(const QPrinterInfo &printer) -- cgit v1.2.3 From 70081096a152d6973d85a1c1466bbc058fe0b24b Mon Sep 17 00:00:00 2001 From: John Layt Date: Mon, 27 Jan 2014 13:31:38 -0500 Subject: QPrintEngine - Switch Windows to QPageLayout Switch the Windows QPrintEngine to use QPageLayout. Change-Id: I2b617fe103980c4efbb0ed367547e436f2d8a5e2 Reviewed-by: Lars Knoll --- src/printsupport/dialogs/qpagesetupdialog_win.cpp | 52 ++- src/printsupport/kernel/qprintengine_win.cpp | 411 ++++++++-------------- src/printsupport/kernel/qprintengine_win_p.h | 39 +- 3 files changed, 193 insertions(+), 309 deletions(-) (limited to 'src') diff --git a/src/printsupport/dialogs/qpagesetupdialog_win.cpp b/src/printsupport/dialogs/qpagesetupdialog_win.cpp index 345e698b82..5da87cce18 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_win.cpp +++ b/src/printsupport/dialogs/qpagesetupdialog_win.cpp @@ -106,42 +106,40 @@ int QPageSetupDialog::exec() psd.hwndOwner = parentWindow ? (HWND)QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", parentWindow) : 0; psd.Flags = PSD_MARGINS; - double multiplier = 1; - switch (QLocale::system().measurementSystem()) { - case QLocale::MetricSystem: - psd.Flags |= PSD_INHUNDREDTHSOFMILLIMETERS; - multiplier = 1; + QPageLayout layout = d->printer->pageLayout(); + switch (layout.units()) { + case QPageLayout::Millimeter: + case QPageLayout::Inch: break; - case QLocale::ImperialSystem: - case QLocale::ImperialUKSystem: - psd.Flags |= PSD_INTHOUSANDTHSOFINCHES; - multiplier = 25.4/10; + case QPageLayout::Point: + case QPageLayout::Pica: + case QPageLayout::Didot: + case QPageLayout::Cicero: + layout.setUnits(QLocale::system().measurementSystem() == QLocale::MetricSystem ? QPageLayout::Millimeter + : QPageLayout::Inch); break; } - - QRect marginRect = ep->getPageMargins(); - psd.rtMargin.left = marginRect.left() / multiplier; - psd.rtMargin.top = marginRect.top() / multiplier; - psd.rtMargin.right = marginRect.width() / multiplier;; - psd.rtMargin.bottom = marginRect.height() / multiplier;; + qreal multiplier = 1.0; + if (layout.units() == QPageLayout::Millimeter) { + psd.Flags |= PSD_INHUNDREDTHSOFMILLIMETERS; + multiplier = 100.0; + } else { // QPageLayout::Inch) + psd.Flags |= PSD_INTHOUSANDTHSOFINCHES; + multiplier = 1000.0; + } + psd.rtMargin.left = layout.margins().left() * multiplier; + psd.rtMargin.top = layout.margins().top() * multiplier; + psd.rtMargin.right = layout.margins().right() * multiplier; + psd.rtMargin.bottom = layout.margins().bottom() * multiplier; QDialog::setVisible(true); bool result = PageSetupDlg(&psd); QDialog::setVisible(false); if (result) { engine->setGlobalDevMode(psd.hDevNames, psd.hDevMode); - - QRect theseMargins = QRect(psd.rtMargin.left * multiplier, - psd.rtMargin.top * multiplier, - psd.rtMargin.right * multiplier, - psd.rtMargin.bottom * multiplier); - - if (theseMargins != marginRect) { - ep->setPageMargins(psd.rtMargin.left * multiplier, - psd.rtMargin.top * multiplier, - psd.rtMargin.right * multiplier, - psd.rtMargin.bottom * multiplier); - } + d->printer->setPageMargins(QMarginsF(psd.rtMargin.left / multiplier, psd.rtMargin.right / multiplier, + psd.rtMargin.top / multiplier, psd.rtMargin.bottom / multiplier), + layout.units()); // copy from our temp DEVMODE struct if (!engine->globalDevMode() && hDevMode) { diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 6aec4919fd..78532f50dd 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -70,8 +70,10 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits); // #define QT_DEBUG_DRAW +// #define QT_DEBUG_METRICS static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc, bool convertToText, const QTransform &xform, const QPointF &topLeft); @@ -90,7 +92,7 @@ QWin32PrintEngine::QWin32PrintEngine(QPrinter::PrinterMode mode) QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); if (ps) d->m_printDevice = ps->createDefaultPrintDevice(); - d->m_pageSize = d->m_printDevice.defaultPageSize(); + d->m_pageLayout.setPageSize(d->m_printDevice.defaultPageSize()); d->initialize(); } @@ -155,6 +157,11 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev) if (!ok) cleanUp(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::begin()"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS + return ok; } @@ -217,6 +224,11 @@ bool QWin32PrintEngine::newPage() if (transparent) SetBkMode(d->hdc, TRANSPARENT); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::newPage()"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS + // ### return true; @@ -310,21 +322,11 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem SelectObject(d->hdc, CreatePen(PS_SOLID, 1, cf)); SetTextColor(d->hdc, cf); - draw_text_item_win(p, ti, d->hdc, convertToText, d->matrix, d->devPaperRect.topLeft()); + draw_text_item_win(p, ti, d->hdc, convertToText, d->matrix, QPointF(0.0, 0.0)); DeleteObject(SelectObject(d->hdc,GetStockObject(HOLLOW_BRUSH))); DeleteObject(SelectObject(d->hdc,GetStockObject(BLACK_PEN))); } -static inline qreal mmToInches(double mm) -{ - return mm*0.039370147; -} - -static inline qreal inchesToMM(double in) -{ - return in/0.039370147; -} - int QWin32PrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const { Q_D(const QWin32PrintEngine); @@ -337,40 +339,18 @@ int QWin32PrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const switch (m) { case QPaintDevice::PdmWidth: - if (d->has_custom_paper_size) { - val = qRound(d->paper_size.width() * res / 72.0); - } else { - int logPixelsX = GetDeviceCaps(d->hdc, LOGPIXELSX); - if (logPixelsX == 0) { - qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, " - "might be a driver problem"); - logPixelsX = 600; // Reasonable default - } - val = res - * GetDeviceCaps(d->hdc, d->fullPage ? PHYSICALWIDTH : HORZRES) - / logPixelsX; - } - if (d->pageMarginsSet) - val -= int(mmToInches((d->previousDialogMargins.left() + - d->previousDialogMargins.width()) / 100.0) * res); + val = d->m_paintRectPixels.width(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::metric(PdmWidth) = " << val; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; case QPaintDevice::PdmHeight: - if (d->has_custom_paper_size) { - val = qRound(d->paper_size.height() * res / 72.0); - } else { - int logPixelsY = GetDeviceCaps(d->hdc, LOGPIXELSY); - if (logPixelsY == 0) { - qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, " - "might be a driver problem"); - logPixelsY = 600; // Reasonable default - } - val = res - * GetDeviceCaps(d->hdc, d->fullPage ? PHYSICALHEIGHT : VERTRES) - / logPixelsY; - } - if (d->pageMarginsSet) - val -= int(mmToInches((d->previousDialogMargins.top() + - d->previousDialogMargins.height()) / 100.0) * res); + val = d->m_paintRectPixels.height(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::metric(PdmHeight) = " << val; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; case QPaintDevice::PdmDpiX: val = res; @@ -385,46 +365,18 @@ int QWin32PrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const val = GetDeviceCaps(d->hdc, LOGPIXELSY); break; case QPaintDevice::PdmWidthMM: - if (d->has_custom_paper_size) { - val = qRound(d->paper_size.width()*25.4/72); - } else { - if (!d->fullPage) { - val = GetDeviceCaps(d->hdc, HORZSIZE); - } else { - float wi = 25.4 * GetDeviceCaps(d->hdc, PHYSICALWIDTH); - int logPixelsX = GetDeviceCaps(d->hdc, LOGPIXELSX); - if (logPixelsX == 0) { - qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, " - "might be a driver problem"); - logPixelsX = 600; // Reasonable default - } - val = qRound(wi / logPixelsX); - } - } - if (d->pageMarginsSet) - val -= (d->previousDialogMargins.left() + - d->previousDialogMargins.width()) / 100.0; + val = d->m_paintSizeMM.width(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::metric(PdmWidthMM) = " << val; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; case QPaintDevice::PdmHeightMM: - if (d->has_custom_paper_size) { - val = qRound(d->paper_size.height()*25.4/72); - } else { - if (!d->fullPage) { - val = GetDeviceCaps(d->hdc, VERTSIZE); - } else { - float hi = 25.4 * GetDeviceCaps(d->hdc, PHYSICALHEIGHT); - int logPixelsY = GetDeviceCaps(d->hdc, LOGPIXELSY); - if (logPixelsY == 0) { - qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, " - "might be a driver problem"); - logPixelsY = 600; // Reasonable default - } - val = qRound(hi / logPixelsY); - } - } - if (d->pageMarginsSet) - val -= (d->previousDialogMargins.top() + - d->previousDialogMargins.height()) / 100.0; + val = d->m_paintSizeMM.height(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::metric(PdmHeightMM) = " << val; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; case QPaintDevice::PdmNumColors: { @@ -943,20 +895,15 @@ void QWin32PrintEnginePrivate::initialize() if (devMode) { num_copies = devMode->dmCopies; devMode->dmCollate = DMCOLLATE_TRUE; - updatePageSize(); + updatePageLayout(); } initHDC(); -#ifdef QT_DEBUG_DRAW - qDebug() << "QWin32PrintEngine::initialize()" << endl - << " - paperRect" << devPaperRect << endl - << " - pageRect" << devPageRect << endl - << " - stretch_x" << stretch_x << endl - << " - stretch_y" << stretch_y << endl - << " - origin_x" << origin_x << endl - << " - origin_y" << origin_y << endl; -#endif +#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::initialize()"; + debugMetrics(); +#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS } void QWin32PrintEnginePrivate::initHDC() @@ -989,50 +936,6 @@ void QWin32PrintEnginePrivate::initHDC() default: break; } - - initDevRects(); -} - -void QWin32PrintEnginePrivate::initDevRects() -{ - devPaperRect = QRect(0, 0, - GetDeviceCaps(hdc, PHYSICALWIDTH), - GetDeviceCaps(hdc, PHYSICALHEIGHT)); - devPhysicalPageRect = QRect(GetDeviceCaps(hdc, PHYSICALOFFSETX), - GetDeviceCaps(hdc, PHYSICALOFFSETY), - GetDeviceCaps(hdc, HORZRES), - GetDeviceCaps(hdc, VERTRES)); - if (!pageMarginsSet) - devPageRect = devPhysicalPageRect; - else - devPageRect = devPaperRect.adjusted(qRound(mmToInches(previousDialogMargins.left() / 100.0) * dpi_x), - qRound(mmToInches(previousDialogMargins.top() / 100.0) * dpi_y), - -qRound(mmToInches(previousDialogMargins.width() / 100.0) * dpi_x), - -qRound(mmToInches(previousDialogMargins.height() / 100.0) * dpi_y)); - updateOrigin(); -} - -void QWin32PrintEnginePrivate::setPageMargins(int marginLeft, int marginTop, int marginRight, int marginBottom) -{ - pageMarginsSet = true; - previousDialogMargins = QRect(marginLeft, marginTop, marginRight, marginBottom); - - devPageRect = devPaperRect.adjusted(qRound(mmToInches(marginLeft / 100.0) * dpi_x), - qRound(mmToInches(marginTop / 100.0) * dpi_y), - - qRound(mmToInches(marginRight / 100.0) * dpi_x), - - qRound(mmToInches(marginBottom / 100.0) * dpi_y)); - updateOrigin(); -} - -QRect QWin32PrintEnginePrivate::getPageMargins() const -{ - if (pageMarginsSet) - return previousDialogMargins; - else - return QRect(qRound(inchesToMM(devPhysicalPageRect.left()) * 100.0 / dpi_x), - qRound(inchesToMM(devPhysicalPageRect.top()) * 100.0 / dpi_y), - qRound(inchesToMM(devPaperRect.right() - devPhysicalPageRect.right()) * 100.0 / dpi_x), - qRound(inchesToMM(devPaperRect.bottom() - devPhysicalPageRect.bottom()) * 100.0 / dpi_y)); } void QWin32PrintEnginePrivate::release() @@ -1064,32 +967,10 @@ void QWin32PrintEnginePrivate::doReinit() reinit = true; } else { resetDC(); - initDevRects(); reinit = false; } } -void QWin32PrintEnginePrivate::updateOrigin() -{ - if (fullPage) { - // subtract physical margins to make (0,0) absolute top corner of paper - // then add user defined margins - origin_x = -devPhysicalPageRect.x(); - origin_y = -devPhysicalPageRect.y(); - if (pageMarginsSet) { - origin_x += devPageRect.left(); - origin_y += devPageRect.top(); - } - } else { - origin_x = 0; - origin_y = 0; - if (pageMarginsSet) { - origin_x = devPageRect.left() - devPhysicalPageRect.x(); - origin_y = devPageRect.top() - devPhysicalPageRect.y(); - } - } -} - void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) { Q_D(QWin32PrintEngine); @@ -1154,8 +1035,15 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & break; case PPK_FullPage: - d->fullPage = value.toBool(); - d->updateOrigin(); + if (value.toBool()) + d->m_pageLayout.setMode(QPageLayout::FullPageMode); + else + d->m_pageLayout.setMode(QPageLayout::StandardMode); + d->updateMetrics(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_FullPage," << value.toBool() << + ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; case PPK_CopyCount: // fallthrough @@ -1167,18 +1055,20 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->doReinit(); break; - case PPK_Orientation: - { - if (!d->devMode) - break; - int orientation = value.toInt() == QPrinter::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; - int old_orientation = d->devMode->dmOrientation; - d->devMode->dmOrientation = orientation; - if (d->has_custom_paper_size && old_orientation != orientation) - d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width()); - d->doReinit(); - } + case PPK_Orientation: { + if (!d->devMode) + break; + QPageLayout::Orientation orientation = QPageLayout::Orientation(value.toInt()); + d->devMode->dmOrientation = orientation == QPageLayout::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; + d->m_pageLayout.setOrientation(orientation); + d->updateMetrics(); + d->doReinit(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_Orientation," << orientation << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; + } case PPK_OutputFileName: if (isActive()) { @@ -1196,6 +1086,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (pageSize.isValid()) { d->setPageSize(pageSize); d->doReinit(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_PageSize," << value.toInt() << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS } break; } @@ -1208,6 +1102,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (pageSize.isValid()) { d->setPageSize(pageSize); d->doReinit(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_PaperName," << value.toString() << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS } break; } @@ -1228,7 +1126,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & case PPK_PrinterName: { QString id = value.toString(); - const QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); if (!ps) return; QPrintDevice printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id); @@ -1240,14 +1138,17 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & break; } - case PPK_Resolution: - { - d->resolution = value.toInt(); - - d->stretch_x = d->dpi_x / double(d->resolution); - d->stretch_y = d->dpi_y / double(d->resolution); - } + case PPK_Resolution: { + d->resolution = value.toInt(); + d->stretch_x = d->dpi_x / double(d->resolution); + d->stretch_y = d->dpi_y / double(d->resolution); + d->updateMetrics(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_Resolution," << value.toInt() << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; + } case PPK_WindowsPageSize: { if (!d->devMode) @@ -1256,6 +1157,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (pageSize.isValid()) { d->setPageSize(pageSize); d->doReinit(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_WindowsPageSize," << value.toInt() << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; } break; @@ -1268,21 +1173,25 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (pageSize.isValid()) { d->setPageSize(pageSize); d->doReinit(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_CustomPaperSize," << value.toSizeF() << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS } break; } - case PPK_PageMargins: - { + case PPK_PageMargins: { QList margins(value.toList()); Q_ASSERT(margins.size() == 4); - int left, top, right, bottom; - // specified in 1/100 mm - left = (margins.at(0).toReal()*25.4/72.0) * 100; - top = (margins.at(1).toReal()*25.4/72.0) * 100; - right = (margins.at(2).toReal()*25.4/72.0) * 100; - bottom = (margins.at(3).toReal()*25.4/72.0) * 100; - d->setPageMargins(left, top, right, bottom); + d->m_pageLayout.setUnits(QPageLayout::Point); + d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(), + margins.at(2).toReal(), margins.at(3).toReal())); + d->updateMetrics(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_PageMargins," << margins << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS break; } @@ -1340,7 +1249,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_FullPage: - value = d->fullPage; + value = d->m_pageLayout.mode() == QPageLayout::FullPageMode; break; case PPK_CopyCount: @@ -1356,13 +1265,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_Orientation: - { - if (!d->devMode) { - value = QPrinter::Portrait; - } else { - value = (d->devMode->dmOrientation == DMORIENT_LANDSCAPE) ? QPrinter::Landscape : QPrinter::Portrait; - } - } + value = d->m_pageLayout.orientation(); break; case PPK_OutputFileName: @@ -1370,39 +1273,21 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_PageRect: - if (d->has_custom_paper_size) { - QRect rect(0, 0, - qRound(d->paper_size.width() * d->resolution / 72.0), - qRound(d->paper_size.height() * d->resolution / 72.0)); - if (d->pageMarginsSet) { - rect = rect.adjusted(qRound(mmToInches(d->previousDialogMargins.left()/100.0) * d->resolution), - qRound(mmToInches(d->previousDialogMargins.top()/100.0) * d->resolution), - -qRound(mmToInches(d->previousDialogMargins.width()/100.0) * d->resolution), - -qRound(mmToInches(d->previousDialogMargins.height()/100.0) * d->resolution)); - } - value = rect; - } else { - value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0) - .mapRect(d->fullPage ? d->devPhysicalPageRect : d->devPageRect); - } + // PageRect is returned in device pixels + value = d->m_pageLayout.paintRectPixels(d->resolution); break; case PPK_PageSize: - value = d->m_pageSize.id(); + value = d->m_pageLayout.pageSize().id(); break; case PPK_PaperRect: - if (d->has_custom_paper_size) { - value = QRect(0, 0, - qRound(d->paper_size.width() * d->resolution / 72.0), - qRound(d->paper_size.height() * d->resolution / 72.0)); - } else { - value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0).mapRect(d->devPaperRect); - } + // PaperRect is returned in device pixels + value = d->m_pageLayout.fullRectPixels(d->resolution); break; case PPK_PaperName: - value = d->m_pageSize.name(); + value = d->m_pageLayout.pageSize().name(); break; case PPK_PaperSource: @@ -1437,7 +1322,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const } case PPK_WindowsPageSize: - value = d->m_pageSize.windowsId(); + value = d->m_pageLayout.pageSize().windowsId(); break; case PPK_PaperSources: { @@ -1449,27 +1334,14 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const } case PPK_CustomPaperSize: - if (property(PPK_Orientation) == QPrinter::Landscape) - value = d->m_pageSize.sizePoints().transposed(); - else - value = d->m_pageSize.sizePoints(); + value = d->m_pageLayout.fullRectPoints().size(); break; - case PPK_PageMargins: - { - QList margins; - if (d->has_custom_paper_size && !d->pageMarginsSet) { - margins << 0 << 0 << 0 << 0; - } else { - QRect pageMargins(d->getPageMargins()); - - // specified in 1/100 mm - margins << (mmToInches(pageMargins.left()/100.0) * 72) - << (mmToInches(pageMargins.top()/100.0) * 72) - << (mmToInches(pageMargins.width()/100.0) * 72) - << (mmToInches(pageMargins.height()/100.0) * 72); - } - value = margins; + case PPK_PageMargins: { + QList list; + QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point); + list << margins.left() << margins.top() << margins.right() << margins.bottom(); + value = list; break; } @@ -1533,7 +1405,7 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD d->hdc = CreateDC(NULL, reinterpret_cast(d->m_printDevice.id().utf16()), 0, dm); d->num_copies = d->devMode->dmCopies; - d->updatePageSize(); + d->updatePageLayout(); if (!OpenPrinter((wchar_t*)d->m_printDevice.id().utf16(), &d->hPrinter, 0)) qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); @@ -1541,6 +1413,11 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD if (d->hdc) d->initHDC(); + +#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setGlobalDevMode()"; + debugMetrics(); +#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS } HGLOBAL QWin32PrintEngine::globalDevMode() @@ -1549,52 +1426,76 @@ HGLOBAL QWin32PrintEngine::globalDevMode() return d->globalDevMode; } - void QWin32PrintEnginePrivate::setPageSize(const QPageSize &pageSize) { if (!pageSize.isValid()) return; // Use the printer page size if supported - QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize); - m_pageSize = printerPageSize.isValid() ? printerPageSize : pageSize; + const QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize); + const QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize; - if (devMode->dmOrientation == DMORIENT_LANDSCAPE) - paper_size = pageSize.size(QPage::Point).transposed(); - else - paper_size = pageSize.size(QPage::Point); + const QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution); + m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units())); // Setup if Windows custom size, i.e. not a known Windows ID if (printerPageSize.isValid()) { has_custom_paper_size = false; - devMode->dmPaperSize = m_pageSize.windowsId(); + devMode->dmPaperSize = m_pageLayout.pageSize().windowsId(); devMode->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH); devMode->dmPaperWidth = 0; devMode->dmPaperLength = 0; } else { - has_custom_paper_size = true; devMode->dmPaperSize = DMPAPER_USER; devMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH; // Size in tenths of a millimeter - const QSizeF sizeMM = m_pageSize.size(QPage::Millimeter); + const QSizeF sizeMM = m_pageLayout.pageSize().size(QPageSize::Millimeter); devMode->dmPaperWidth = qRound(sizeMM.width() * 10.0); devMode->dmPaperLength = qRound(sizeMM.height() * 10.0); } + updateMetrics(); } -// Called by print dialogs after devMode updated with new page size -// Know devMode->dmPaperSize is valid, refresh QPageSize to match -void QWin32PrintEnginePrivate::updatePageSize() +// Update the page layout after any changes made to devMode +void QWin32PrintEnginePrivate::updatePageLayout() { + // Update orientation first as is needed to obtain printable margins when changing page size + m_pageLayout.setOrientation(devMode->dmOrientation == DMORIENT_LANDSCAPE ? QPageLayout::Landscape : QPageLayout::Portrait); if (devMode->dmPaperSize >= DMPAPER_USER) { // Is a custom size QPageSize pageSize = QPageSize(QSizeF(devMode->dmPaperWidth / 10.0f, devMode->dmPaperLength / 10.0f), - QPage::Millimeter); + QPageSize::Millimeter); setPageSize(pageSize); } else { // Is a supported size setPageSize(QPageSize(QPageSize::id(devMode->dmPaperSize))); } + updateMetrics(); +} + +// Update the cached page paint metrics whenever page layout is changed +void QWin32PrintEnginePrivate::updateMetrics() +{ + m_paintRectPixels = m_pageLayout.paintRectPixels(resolution); + QSizeF sizeMM = m_pageLayout.paintRect(QPageLayout::Millimeter).size(); + m_paintSizeMM = QSize(qRound(sizeMM.width()), qRound(sizeMM.height())); + // Calculate the origin using the physical device pixels, not our paint pixels + // Origin is defined as User Margins - Device Margins + QMarginsF margins = m_pageLayout.margins(QPageLayout::Millimeter) / 25.4; + origin_x = qRound(margins.left() * dpi_x) - GetDeviceCaps(hdc, PHYSICALOFFSETX); + origin_y = qRound(margins.top() * dpi_y) - GetDeviceCaps(hdc, PHYSICALOFFSETY); +} + +void QWin32PrintEnginePrivate::debugMetrics() const +{ + qDebug() << " " << "m_pageLayout = " << m_pageLayout; + qDebug() << " " << "m_paintRectPixels = " << m_paintRectPixels; + qDebug() << " " << "m_paintSizeMM = " << m_paintSizeMM; + qDebug() << " " << "resolution = " << resolution; + qDebug() << " " << "stretch = " << stretch_x << stretch_y; + qDebug() << " " << "origin = " << origin_x << origin_y; + qDebug() << " " << "dpi = " << dpi_x << dpi_y; + qDebug() << ""; } static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc, diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index 61bf63346b..9b944d5921 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -129,12 +129,10 @@ public: mode(QPrinter::ScreenResolution), state(QPrinter::Idle), resolution(0), - pageMarginsSet(false), + m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))), num_copies(1), printToFile(false), - fullPage(false), - reinit(false), - has_custom_paper_size(false) + reinit(false) { } @@ -173,13 +171,9 @@ public: void strokePath_dev(const QPainterPath &path, const QColor &color, qreal width); void setPageSize(const QPageSize &pageSize); - void updatePageSize(); - - void updateOrigin(); - - void initDevRects(); - void setPageMargins(int margin_left, int margin_top, int margin_right, int margin_bottom); - QRect getPageMargins() const; + void updatePageLayout(); + void updateMetrics(); + void debugMetrics() const; // Windows GDI printer references. HANDLE hPrinter; @@ -205,21 +199,13 @@ public: int resolution; // Page Layout - QPageSize m_pageSize; - - // This QRect is used to store the exact values - // entered into the PageSetup Dialog because those are - // entered in mm but are since converted to device coordinates. - // If they were to be converted back when displaying the dialog - // again, there would be inaccuracies so when the user entered 10 - // it may show up as 9.99 the next time the dialog is opened. - // We don't want that confusion. - QRect previousDialogMargins; - - bool pageMarginsSet; - QRect devPageRect; - QRect devPhysicalPageRect; - QRect devPaperRect; + QPageLayout m_pageLayout; + + // Page metrics cache + QRect m_paintRectPixels; + QSize m_paintSizeMM; + + // Windows painting qreal stretch_x; qreal stretch_y; int origin_x; @@ -231,7 +217,6 @@ public: int num_copies; uint printToFile : 1; - uint fullPage : 1; uint reinit : 1; uint complex_xform : 1; -- cgit v1.2.3 From dbc50e06df8465e6de02ac0b4458e1a3f3f8568c Mon Sep 17 00:00:00 2001 From: John Layt Date: Mon, 30 Dec 2013 18:04:40 +0100 Subject: QPrinter - Use QPageSize and QPageLayout Use QPageSize and QPageMargins to get/set values in the print engines, add api to directly set the values, and rewrite the docs to make the paper-based api obsolete instead of the page-based api. Add new PPK keys to pass QPageSize, QPageMargins and QPageLayout to the print engines to ensure no level of detail is lost, e.g. for custom sizes passed to QPrinter. [ChangeLog][QtPrintSupport][QPrinter] QPrinter can now use QPageSize and QPageLayout in the public api to control the page layout for a print job. Change-Id: Iee39a4042bcd6141d29b0a82b49066d7a7a78120 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 32 +- src/plugins/printsupport/cups/qcupsprintengine.cpp | 12 + src/printsupport/dialogs/qpagesetupdialog_unix.cpp | 13 +- src/printsupport/dialogs/qprintdialog_mac.mm | 41 ++ src/printsupport/kernel/qprintengine.h | 5 + src/printsupport/kernel/qprintengine_pdf.cpp | 30 ++ src/printsupport/kernel/qprintengine_win.cpp | 60 ++- src/printsupport/kernel/qprinter.cpp | 472 ++++++++++++--------- src/printsupport/kernel/qprinter.h | 9 + src/printsupport/kernel/qprinter_p.h | 5 +- 10 files changed, 458 insertions(+), 221 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index bfe44c7ab3..95713eba59 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -42,7 +42,7 @@ #include "qprintengine_mac_p.h" #include "qcocoaprintersupport.h" #include -#include +#include #include #include @@ -559,6 +559,26 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va margins.at(2).toReal(), margins.at(3).toReal())); break; } + case PPK_QPageSize: + d->setPageSize(value.value()); + break; + case PPK_QPageMargins: { + QPair pair = value.value >(); + d->m_pageLayout.setUnits(pair.second); + d->m_pageLayout.setMargins(pair.first); + break; + } + case PPK_QPageLayout: { + QPageLayout pageLayout = value.value(); + if (pageLayout.isValid() && d->m_printDevice->isValidPageLayout(pageLayout, d->resolution.hRes)) { + setProperty(PPK_QPageSize, QVariant::fromValue(pageLayout.pageSize())); + setProperty(PPK_FullPage, pageLayout.mode() == QPageLayout::FullPageMode); + setProperty(PPK_Orientation, QVariant::fromValue(pageLayout.orientation())); + d->m_pageLayout.setUnits(pageLayout.units()); + d->m_pageLayout.setMargins(pageLayout.margins()); + } + break; + } // No default so that compiler will complain if new keys added and not handled in this engine } } @@ -688,6 +708,16 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const ret = list; break; } + case PPK_QPageSize: + ret.setValue(d->m_pageLayout.pageSize()); + break; + case PPK_QPageMargins: { + QPair pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units()); + ret.setValue(pair); + break; + } + case PPK_QPageLayout: + ret.setValue(d->m_pageLayout); // No default so that compiler will complain if new keys added and not handled in this engine } return ret; diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 2c05a76084..90de1a2a8b 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -96,6 +96,18 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v case PPK_CupsOptions: d->cupsOptions = value.toStringList(); break; + case PPK_QPageSize: + d->setPageSize(value.value()); + break; + case PPK_QPageLayout: { + QPageLayout pageLayout = value.value(); + if (pageLayout.isValid() && d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)) { + d->m_pageLayout = pageLayout; + // Replace the page size with the CUPS page size + d->setPageSize(d->m_printDevice.supportedPageSize(pageLayout.pageSize())); + } + break; + } default: QPdfPrintEngine::setProperty(key, value); break; diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp index d2975ad9da..7b84d8b86f 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp @@ -434,18 +434,7 @@ void QPageSetupWidget::selectPrinter() } if (!preferredSizeMatched) widget.paperSize->setCurrentIndex(cupsDefaultSize); - if (m_printer->d_func()->hasCustomPageMargins) { - m_printer->getPageMargins(&m_leftMargin, &m_topMargin, &m_rightMargin, &m_bottomMargin, QPrinter::Point); - } else { - QByteArray cupsPaperSizeChoice = widget.paperSize->itemData(widget.paperSize->currentIndex()).toByteArray(); - QRect paper = cups.paperRect(cupsPaperSizeChoice); - QRect content = cups.pageRect(cupsPaperSizeChoice); - - m_leftMargin = content.x() - paper.x(); - m_topMargin = content.y() - paper.y(); - m_rightMargin = paper.right() - content.right(); - m_bottomMargin = paper.bottom() - content.bottom(); - } + m_printer->getPageMargins(&m_leftMargin, &m_topMargin, &m_rightMargin, &m_bottomMargin, QPrinter::Point); } else m_cups = false; #endif diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index 67216f7f2a..7194aee22f 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -151,6 +151,47 @@ QT_USE_NAMESPACE } } + // Note this code should be in QCocoaPrintDevice, but that implementation is in the plugin, + // we need to move the dialog implementation into the plugin first to be able to access it. + // Need to tell QPrinter/QPageLayout if the page size or orientation has been changed + PMPageFormat pageFormat = static_cast([printInfo PMPageFormat]); + PMPaper paper; + PMGetPageFormatPaper(pageFormat, &paper); + PMOrientation orientation; + PMGetOrientation(pageFormat, &orientation); + QPageSize pageSize; + QCFString key; + double width = 0; + double height = 0; + // If the PPD name is empty then is custom, for some reason PMPaperIsCustom doesn't work here + PMPaperGetPPDPaperName(paper, &key); + if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) { + QString ppdKey = key; + if (ppdKey.isEmpty()) { + // Is using a custom page size as defined in the Print Dialog custom settings using mm or inches. + // We can't ask PMPaper what those units actually are, we can only get the point size which may return + // slightly wrong results due to rounding. + // Testing shows if using metric/mm then is rounded mm, if imperial/inch is rounded to 2 decimal places + // Even if we pass in our own custom size in mm with decimal places, the dialog will still round it! + // Suspect internal storage is in rounded mm? + if (QLocale().measurementSystem() == QLocale::MetricSystem) { + QSizeF sizef = QSizeF(width, height) / qt_pointMultiplier(QPageLayout::Millimeter); + // Round to 0 decimal places + pageSize = QPageSize(sizef.toSize(), QPageSize::Millimeter); + } else { + qreal multiplier = qt_pointMultiplier(QPageLayout::Inch); + const int w = qRound(width * 100 / multiplier); + const int h = qRound(height * 100 / multiplier); + pageSize = QPageSize(QSizeF(w / 100.0, h / 100.0), QPageSize::Inch); + } + } else { + pageSize = QPlatformPrintDevice::createPageSize(key, QSize(width, height), QString()); + } + } + if (pageSize.isValid() && !pageSize.isEquivalentTo(printer->pageLayout().pageSize())) + printer->setPageSize(pageSize); + printer->setOrientation(orientation == kPMLandscape ? QPrinter::Landscape : QPrinter::Portrait); + dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); } @end diff --git a/src/printsupport/kernel/qprintengine.h b/src/printsupport/kernel/qprintengine.h index 3993a22bef..a69fe01fd4 100644 --- a/src/printsupport/kernel/qprintengine.h +++ b/src/printsupport/kernel/qprintengine.h @@ -45,6 +45,8 @@ #include #include +Q_DECLARE_METATYPE(QMarginsF) + QT_BEGIN_NAMESPACE @@ -85,6 +87,9 @@ public: PPK_CopyCount, PPK_SupportsMultipleCopies, PPK_PaperName, + PPK_QPageSize, + PPK_QPageMargins, + PPK_QPageLayout, PPK_PaperSize = PPK_PageSize, PPK_CustomBase = 0xff00 diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp index c24905009d..d62da0e1d6 100644 --- a/src/printsupport/kernel/qprintengine_pdf.cpp +++ b/src/printsupport/kernel/qprintengine_pdf.cpp @@ -48,6 +48,7 @@ #include #include #include "qprinterinfo.h" +#include #include #include @@ -219,6 +220,24 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va margins.at(2).toReal(), margins.at(3).toReal())); break; } + case PPK_QPageSize: { + QPageSize pageSize = value.value(); + if (pageSize.isValid()) + d->m_pageLayout.setPageSize(pageSize); + break; + } + case PPK_QPageMargins: { + QPair pair = value.value >(); + d->m_pageLayout.setUnits(pair.second); + d->m_pageLayout.setMargins(pair.first); + break; + } + case PPK_QPageLayout: { + QPageLayout pageLayout = value.value(); + if (pageLayout.isValid()) + d->m_pageLayout = pageLayout; + break; + } // No default so that compiler will complain if new keys added and not handled in this engine } } @@ -319,6 +338,17 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const ret = list; break; } + case PPK_QPageSize: + ret.setValue(d->m_pageLayout.pageSize()); + break; + case PPK_QPageMargins: { + QPair pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units()); + ret.setValue(pair); + break; + } + case PPK_QPageLayout: + ret.setValue(d->m_pageLayout); + break; // No default so that compiler will complain if new keys added and not handled in this engine } return ret; diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 78532f50dd..52b67d162b 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -62,6 +62,7 @@ #include #include #include +#include Q_DECLARE_METATYPE(HFONT) Q_DECLARE_METATYPE(LOGFONT) @@ -1195,8 +1196,50 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & break; } - // No default so that compiler will complain if new keys added and not handled in this engine + case PPK_QPageSize: { + // Get the page size from the printer if supported + const QPageSize pageSize = value.value(); + if (pageSize.isValid()) { + d->setPageSize(pageSize); + d->doReinit(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageSize," << pageSize << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS + } + break; + } + case PPK_QPageMargins: { + QPair pair = value.value >(); + d->m_pageLayout.setUnits(pair.second); + d->m_pageLayout.setMargins(pair.first); + d->updateMetrics(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageMargins," << pair.first << pair.second << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS + break; + } + + case PPK_QPageLayout: { + QPageLayout pageLayout = value.value(); + if (pageLayout.isValid() && d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)) { + setProperty(PPK_QPageSize, QVariant::fromValue(pageLayout.pageSize())); + setProperty(PPK_FullPage, pageLayout.mode() == QPageLayout::FullPageMode); + setProperty(PPK_Orientation, QVariant::fromValue(pageLayout.orientation())); + d->m_pageLayout.setUnits(pageLayout.units()); + d->m_pageLayout.setMargins(pageLayout.margins()); + d->updateMetrics(); +#ifdef QT_DEBUG_METRICS + qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageLayout," << pageLayout << ")"; + d->debugMetrics(); +#endif // QT_DEBUG_METRICS + } + break; + } + + // No default so that compiler will complain if new keys added and not handled in this engine } } @@ -1345,8 +1388,21 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const break; } - // No default so that compiler will complain if new keys added and not handled in this engine + case PPK_QPageSize: + value.setValue(d->m_pageLayout.pageSize()); + break; + + case PPK_QPageMargins: { + QPair pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units()); + value.setValue(pair); + break; + } + + case PPK_QPageLayout: + value.setValue(d->m_pageLayout); + break; + // No default so that compiler will complain if new keys added and not handled in this engine } return value; } diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 9e10f5c636..f72a0ae0fb 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -67,39 +67,14 @@ QT_BEGIN_NAMESPACE return; \ } -// NB! This table needs to be in sync with QPrinter::PaperSize -static const float qt_paperSizes[][2] = { - {210, 297}, // A4 - {176, 250}, // B5 - {215.9f, 279.4f}, // Letter - {215.9f, 355.6f}, // Legal - {190.5f, 254}, // Executive - {841, 1189}, // A0 - {594, 841}, // A1 - {420, 594}, // A2 - {297, 420}, // A3 - {148, 210}, // A5 - {105, 148}, // A6 - {74, 105}, // A7 - {52, 74}, // A8 - {37, 52}, // A8 - {1000, 1414}, // B0 - {707, 1000}, // B1 - {31, 44}, // B10 - {500, 707}, // B2 - {353, 500}, // B3 - {250, 353}, // B4 - {125, 176}, // B6 - {88, 125}, // B7 - {62, 88}, // B8 - {44, 62}, // B9 - {163, 229}, // C5E - {105, 241}, // US Common - {110, 220}, // DLE - {210, 330}, // Folio - {431.8f, 279.4f}, // Ledger - {279.4f, 431.8f} // Tabloid -}; +#define ABORT_IF_ACTIVE_RETURN(location, retValue) \ + if (d->printEngine->printerState() == QPrinter::Active) { \ + qWarning("%s: Cannot be changed while printer is active", location); \ + return retValue; \ + } + +extern qreal qt_pixelMultiplier(int resolution); +extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits); /// return the multiplier of converting from the unit value to postscript-points. Q_PRINTSUPPORT_EXPORT double qt_multiplierForUnit(QPrinter::Unit unit, int resolution) @@ -123,28 +98,6 @@ Q_PRINTSUPPORT_EXPORT double qt_multiplierForUnit(QPrinter::Unit unit, int resol return 1.0; } -/// return the QSize from the specified in unit as millimeters -Q_PRINTSUPPORT_EXPORT QSizeF qt_SizeFromUnitToMillimeter(const QSizeF &size, QPrinter::Unit unit, double resolution) -{ - switch (unit) { - case QPrinter::Millimeter: - return size; - case QPrinter::Point: - return size * 0.352777778; - case QPrinter::Inch: - return size * 25.4; - case QPrinter::Pica: - return size * 4.23333333334; - case QPrinter::Didot: - return size * 0.377; - case QPrinter::Cicero: - return size * 4.511666667; - case QPrinter::DevicePixel: - return size * (0.352777778 * 72.0 / resolution); - } - return size; -} - // not static: it's needed in qpagesetupdialog_unix.cpp Q_PRINTSUPPORT_EXPORT QSizeF qt_printerPaperSize(QPrinter::Orientation orientation, QPrinter::PaperSize paperSize, @@ -152,10 +105,12 @@ Q_PRINTSUPPORT_EXPORT QSizeF qt_printerPaperSize(QPrinter::Orientation orientati int resolution) { QPageSize pageSize = QPageSize(QPageSize::PageSizeId(paperSize)); - if (orientation == QPrinter::Landscape) - return pageSize.size(QPage::Unit(unit), resolution).transposed(); + QSizeF sizef; + if (unit == QPrinter::DevicePixel) + sizef = pageSize.size(QPageSize::Point) * qt_multiplierForUnit(unit, resolution); else - return pageSize.size(QPage::Unit(unit), resolution); + sizef = pageSize.size(QPageSize::Unit(unit)); + return orientation == QPrinter::Landscape ? sizef.transposed() : sizef; } QPrinterInfo QPrinterPrivate::findValidPrinter(const QPrinterInfo &printer) @@ -1007,21 +962,165 @@ void QPrinter::setCreator(const QString &creator) d->setProperty(QPrintEngine::PPK_Creator, creator); } +/*! + \since 5.3 + + Sets the page layout to \a newLayout. + + If the \a newLayout is not valid for the current printer then the page + layout will not be changed. For example, if the page size is not supported + by the printer, or if the margins fall outside the printable area. + + Returns true if the page layout was successfully set to \a newLayout. + + \sa pageLayout(), setPageSize(), setPageOrientation(), setPageMargins() +*/ + +bool QPrinter::setPageLayout(const QPageLayout &newLayout) +{ + Q_D(QPrinter); + + if (d->paintEngine->type() != QPaintEngine::Pdf) + ABORT_IF_ACTIVE_RETURN("QPrinter::setPageLayout", false); + + // Try to set the print engine page layout + d->setProperty(QPrintEngine::PPK_QPageLayout, QVariant::fromValue(newLayout)); + + // Set QPagedPaintDevice layout to match the current print engine value + devicePageLayout() = pageLayout(); + + return pageLayout().isEquivalentTo(newLayout); +} + +/*! + \since 5.3 + + Sets the page size to \a pageSize. + + If the \a pageSize is not valid for the current printer then the page + size will not be changed. + + Changing the page size may affect the current page margins if they fall + outside the printable margins for the new page size on the current printer. + + To obtain the current QPageSize use pageLayout().pageSize(). + + Returns true if the page size was successfully set to \a pageSize. + + \sa pageLayout(), setPageLayout() +*/ + +bool QPrinter::setPageSize(const QPageSize &pageSize) +{ + Q_D(QPrinter); + + if (d->paintEngine->type() != QPaintEngine::Pdf) + ABORT_IF_ACTIVE_RETURN("QPrinter::setPageSize", false); + + // Try to set the print engine page size + d->setProperty(QPrintEngine::PPK_QPageSize, QVariant::fromValue(pageSize)); + + // Set QPagedPaintDevice layout to match the current print engine value + devicePageLayout() = pageLayout(); + + return pageLayout().pageSize().isEquivalentTo(pageSize); +} + +/*! + \since 5.3 + + Sets the page \a orientation to QPageLayout::Portrait or QPageLayout::Landscape. + + The printer driver reads this setting and prints the page using the + specified orientation. + + On Windows and Mac, this option can be changed while printing and will + take effect from the next call to newPage(). + + To obtain the current QPageLayout::Orientation use pageLayout().pageOrientation(). + + Returns true if the page orientation was successfully set to \a orientation. + + \sa pageLayout(), setPageLayout() +*/ + +bool QPrinter::setPageOrientation(QPageLayout::Orientation orientation) +{ + Q_D(QPrinter); + + // Set the print engine value + d->setProperty(QPrintEngine::PPK_Orientation, orientation); + + // Set QPagedPaintDevice layout to match the current print engine value + devicePageLayout() = pageLayout(); + + return pageLayout().orientation() == orientation; +} + +/*! + \since 5.3 + + Set the page margins to \a margins in the given \a units. If \a units are + not provided then the current units are used. + + If in Full Page mode then no check is performed on the \a margins set, + otherwise the \a margins must fall within the printable area for the page + size on the current printer. + + To obtain the current page margins use pageLayout().pageMargins(). + + Returns true if the page margins was successfully set to \a margins. + + \sa pageLayout(), setPageLayout() +*/ + +bool QPrinter::setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) +{ + Q_D(QPrinter); + + // Try to set print engine margins + QPair pair = qMakePair(margins, units); + d->setProperty(QPrintEngine::PPK_QPageMargins, QVariant::fromValue(pair)); + + // Set QPagedPaintDevice layout to match the current print engine value + devicePageLayout() = pageLayout(); + + return pageLayout().margins() == margins && pageLayout().units() == units; +} + +/*! + Returns the current page layout. Use this method to access the current + QPageSize, QPageLayout::Orientation, QMarginsF, fullPageRect() and paintRect(). + + Note that you cannot use the setters on the returned object, you must either + call the QPrinter methods or setPageLayout(). + + \sa setPageLayout(), setPageSize(), setPageOrientation(), setPageMargins() +*/ + +QPageLayout QPrinter::pageLayout() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_QPageLayout).value(); +} /*! + \obsolete Use pageLayout().pageOrientation() instead. + Returns the orientation setting. This is driver-dependent, but is usually QPrinter::Portrait. - \sa setOrientation() + \sa pageLayout() */ QPrinter::Orientation QPrinter::orientation() const { - Q_D(const QPrinter); - return QPrinter::Orientation(d->printEngine->property(QPrintEngine::PPK_Orientation).toInt()); + return QPrinter::Orientation(pageLayout().orientation()); } /*! + \obsolete Use setPageOrientation() instead. + Sets the print orientation to \a orientation. The orientation can be either QPrinter::Portrait or @@ -1033,32 +1132,34 @@ QPrinter::Orientation QPrinter::orientation() const On Windows and Mac, this option can be changed while printing and will take effect from the next call to newPage(). - \sa orientation() + \sa setPageOrientation() */ void QPrinter::setOrientation(Orientation orientation) { - Q_D(QPrinter); - d->setProperty(QPrintEngine::PPK_Orientation, orientation); + setPageOrientation(QPageLayout::Orientation(orientation)); } - /*! \since 4.4 + + \obsolete Use pageLayout().pageSize().id() instead. + Returns the printer paper size. The default value is driver-dependent. - \sa setPaperSize(), pageRect(), paperRect() + \sa pageLayout() */ QPrinter::PaperSize QPrinter::paperSize() const { - Q_D(const QPrinter); - return QPrinter::PaperSize(d->printEngine->property(QPrintEngine::PPK_PaperSize).toInt()); + return pageSize(); } /*! \since 4.4 + \obsolete Use setPageSize(QPageSize) instead. + Sets the printer paper size to \a newPaperSize if that size is supported. The result is undefined if \a newPaperSize is not supported. @@ -1068,116 +1169,103 @@ QPrinter::PaperSize QPrinter::paperSize() const This function is useful mostly for setting a default value that the user can override in the print dialog. - \sa paperSize(), PaperSize, setFullPage(), setResolution(), pageRect(), paperRect() + \sa setPageSize() */ void QPrinter::setPaperSize(PaperSize newPaperSize) { - setPageSize(newPaperSize); + setPageSize(QPageSize(QPageSize::PageSizeId(newPaperSize))); } /*! - \obsolete + \obsolete Use pageLayout().pageSize().id() instead. Returns the printer page size. The default value is driver-dependent. - Use paperSize() instead. + \sa pageLayout() */ QPrinter::PageSize QPrinter::pageSize() const { - return paperSize(); + return QPrinter::PaperSize(pageLayout().pageSize().id()); } /*! - \obsolete + \obsolete Use setPageSize(QPageSize) instead. Sets the printer page size based on \a newPageSize. - Use setPaperSize() instead. + \sa setPageSize() */ void QPrinter::setPageSize(PageSize newPageSize) { - QPagedPaintDevice::setPageSize(newPageSize); - - Q_D(QPrinter); - if (d->paintEngine->type() != QPaintEngine::Pdf) - ABORT_IF_ACTIVE("QPrinter::setPaperSize"); - if (newPageSize < 0 || newPageSize >= NPageSize) { - qWarning("QPrinter::setPaperSize: Illegal paper size %d", newPageSize); - return; - } - d->setProperty(QPrintEngine::PPK_PaperSize, newPageSize); - d->hasUserSetPageSize = true; + setPageSize(QPageSize(QPageSize::PageSizeId(newPageSize))); } /*! \since 4.4 + \obsolete Use setPageSize(QPageSize) instead. + Sets the paper size based on \a paperSize in \a unit. Note that the paper size is defined in a portrait layout, regardless of what the current printer orientation is set to. - \sa paperSize() + \sa setPageSize() */ void QPrinter::setPaperSize(const QSizeF &paperSize, QPrinter::Unit unit) { - Q_D(QPrinter); - if (d->paintEngine->type() != QPaintEngine::Pdf) - ABORT_IF_ACTIVE("QPrinter::setPaperSize"); - setPageSizeMM(qt_SizeFromUnitToMillimeter(paperSize, unit, resolution())); + setPageSize(QPageSize(paperSize, QPageSize::Unit(unit))); } /*! \reimp + \obsolete Use setPageSize(QPageSize) instead. + + Use setPageSize(QPageSize) instead. + Note that the page size is defined in a portrait layout, regardless of what the current printer orientation is set to. + + \sa setPageSize() */ void QPrinter::setPageSizeMM(const QSizeF &size) { - Q_D(QPrinter); - - QPagedPaintDevice::setPageSizeMM(size); - - QSizeF s = size * 72./25.4; - d->setProperty(QPrintEngine::PPK_CustomPaperSize, s); - d->hasUserSetPageSize = true; + setPageSize(QPageSize(size, QPageSize::Millimeter)); } /*! \since 4.4 + \obsolete Use pageLayout().pageSize().size() or + pageLayout().fullPageSize() instead. + Returns the paper size in \a unit. Note that the returned size reflects the current paper orientation. - \sa setPaperSize() + \sa pageLayout() */ QSizeF QPrinter::paperSize(Unit unit) const { - Q_D(const QPrinter); - int res = resolution(); - const qreal multiplier = qt_multiplierForUnit(unit, res); - PaperSize paperType = paperSize(); - if (paperType == Custom) { - QSizeF size = d->printEngine->property(QPrintEngine::PPK_CustomPaperSize).toSizeF(); - return QSizeF(size.width() / multiplier, size.height() / multiplier); - } - else { - return qt_printerPaperSize(orientation(), paperType, unit, res); - } + if (unit == QPrinter::DevicePixel) + return pageLayout().fullRectPixels(resolution()).size(); + else + return pageLayout().fullRect(QPageLayout::Unit(unit)).size(); } /*! \since 5.1 + \obsolete Use setPageSize(QPageSize) instead. + Sets the paper used by the printer to \a paperName. - \sa paperName() + \sa setPageSize() */ void QPrinter::setPaperName(const QString &paperName) @@ -1191,9 +1279,13 @@ void QPrinter::setPaperName(const QString &paperName) /*! \since 5.1 + \obsolete Use pageLayout().pageSize().name() instead. + Returns the paper name of the paper set on the printer. The default value for this is driver-dependent. + + \sa pageLayout() */ QString QPrinter::paperName() const @@ -1438,13 +1530,16 @@ void QPrinter::setCollateCopies(bool collate) printer's margins, so the application must account for the margins itself. - \sa fullPage(), setPaperSize(), width(), height() + \sa fullPage(), pageLayout(), setPageSize(), width(), height() */ void QPrinter::setFullPage(bool fp) { Q_D(QPrinter); + // Set the print engine d->setProperty(QPrintEngine::PPK_FullPage, fp); + // Set QPagedPaintDevice layout to match the current print engine value + devicePageLayout() = pageLayout(); } @@ -1455,7 +1550,7 @@ void QPrinter::setFullPage(bool fp) See setFullPage() for details and caveats. - \sa setFullPage(), PaperSize + \sa setFullPage(), pageLayout() */ bool QPrinter::fullPage() const @@ -1635,19 +1730,10 @@ QPrinter::DuplexMode QPrinter::duplex() const */ QRectF QPrinter::pageRect(Unit unit) const { - Q_D(const QPrinter); - int res = resolution(); - const qreal multiplier = qt_multiplierForUnit(unit, res); - // the page rect is in device pixels - QRect devRect(d->printEngine->property(QPrintEngine::PPK_PageRect).toRect()); - if (unit == DevicePixel) - return devRect; - QRectF diRect(devRect.x()*72.0/res, - devRect.y()*72.0/res, - devRect.width()*72.0/res, - devRect.height()*72.0/res); - return QRectF(diRect.x()/multiplier, diRect.y()/multiplier, - diRect.width()/multiplier, diRect.height()/multiplier); + if (unit == QPrinter::DevicePixel) + return pageLayout().paintRectPixels(resolution()); + else + return pageLayout().paintRect(QPageLayout::Unit(unit)); } @@ -1661,29 +1747,22 @@ QRectF QPrinter::pageRect(Unit unit) const */ QRectF QPrinter::paperRect(Unit unit) const { - Q_D(const QPrinter); - int res = resolution(); - const qreal multiplier = qt_multiplierForUnit(unit, resolution()); - // the page rect is in device pixels - QRect devRect(d->printEngine->property(QPrintEngine::PPK_PaperRect).toRect()); - if (unit == DevicePixel) - return devRect; - QRectF diRect(devRect.x()*72.0/res, - devRect.y()*72.0/res, - devRect.width()*72.0/res, - devRect.height()*72.0/res); - return QRectF(diRect.x()/multiplier, diRect.y()/multiplier, - diRect.width()/multiplier, diRect.height()/multiplier); + if (unit == QPrinter::DevicePixel) + return pageLayout().fullRectPixels(resolution()); + else + return pageLayout().fullRect(QPageLayout::Unit(unit)); } /*! + \obsolete Use pageLayout().paintRect() instead. + Returns the page's rectangle; this is usually smaller than the paperRect() since the page normally has margins between its borders and the paper. The unit of the returned rectangle is DevicePixel. - \sa paperSize() + \sa pageLayout() */ QRect QPrinter::pageRect() const { @@ -1692,12 +1771,14 @@ QRect QPrinter::pageRect() const } /*! + \obsolete Use pageLayout().fullPageRect() instead. + Returns the paper's rectangle; this is usually larger than the pageRect(). The unit of the returned rectangle is DevicePixel. - \sa pageRect() + \sa pageLayout() */ QRect QPrinter::paperRect() const { @@ -1705,61 +1786,69 @@ QRect QPrinter::paperRect() const return d->printEngine->property(QPrintEngine::PPK_PaperRect).toRect(); } - /*! \since 4.4 + \obsolete Use setPageMargins(QMarginsF, QPageLayout::Unit) instead. + This function sets the \a left, \a top, \a right and \a bottom page margins for this printer. The unit of the margins are specified with the \a unit parameter. - \sa getPageMargins() + \sa setPageMargins() */ void QPrinter::setPageMargins(qreal left, qreal top, qreal right, qreal bottom, QPrinter::Unit unit) { - const qreal multiplier = qt_multiplierForUnit(unit, resolution()) * 25.4/72.; - Margins m = { left*multiplier, right*multiplier, top*multiplier, bottom*multiplier }; - setMargins(m); + if (unit == QPrinter::DevicePixel) { + QMarginsF margins = QMarginsF(left, top, right, bottom); + margins *= qt_pixelMultiplier(resolution()); + margins = qt_convertMargins(margins, QPageLayout::Point, pageLayout().units()); + setPageMargins(margins, pageLayout().units()); + } else { + setPageMargins(QMarginsF(left, top, right, bottom), QPageLayout::Unit(unit)); + } } /*! - \reimp + \reimp + + \obsolete Use setPageMargins(QMarginsF, QPageLayout::Unit) instead. + + \sa setPageMargins() */ void QPrinter::setMargins(const Margins &m) { - Q_D(QPrinter); - - // set margins also to super class - QPagedPaintDevice::setMargins(m); - - const qreal multiplier = 72./25.4; - QList margins; - margins << (m.left * multiplier) << (m.top * multiplier) - << (m.right * multiplier) << (m.bottom * multiplier); - d->setProperty(QPrintEngine::PPK_PageMargins, margins); - d->hasCustomPageMargins = true; + setPageMargins(QMarginsF(m.left, m.top, m.right, m.bottom), QPageLayout::Millimeter); } - /*! \since 4.4 + \obsolete Use pageLayout().pageMargins() instead. + Returns the page margins for this printer in \a left, \a top, \a right, \a bottom. The unit of the returned margins are specified with the \a unit parameter. - \sa setPageMargins() + \sa pageLayout(), setPageMargins() */ void QPrinter::getPageMargins(qreal *left, qreal *top, qreal *right, qreal *bottom, QPrinter::Unit unit) const { - Q_D(const QPrinter); - Q_ASSERT(left && top && right && bottom); - const qreal multiplier = qt_multiplierForUnit(unit, resolution()); - QList margins(d->printEngine->property(QPrintEngine::PPK_PageMargins).toList()); - *left = margins.at(0).toReal() / multiplier; - *top = margins.at(1).toReal() / multiplier; - *right = margins.at(2).toReal() / multiplier; - *bottom = margins.at(3).toReal() / multiplier; + QMarginsF margins; + if (unit == QPrinter::DevicePixel) { + QMargins tmp = pageLayout().marginsPixels(resolution()); + margins = QMarginsF(tmp.left(), tmp.top(), tmp.right(), tmp.bottom()); + } else { + margins = pageLayout().margins(QPageLayout::Unit(unit)); + } + if (left) + *left = margins.left(); + if (right) + *right = margins.right(); + if (top) + *top = margins.top(); + if (bottom) + *bottom = margins.bottom(); } /*! @@ -1795,13 +1884,15 @@ QPrintEngine *QPrinter::printEngine() const #if defined (Q_OS_WIN) /*! + \obsolete Use QPageSize::id(windowsId) and setPageLayout(QPageSize) instead. + Sets the page size to be used by the printer under Windows to \a pageSize. \warning This function is not portable so you may prefer to use setPaperSize() instead. - \sa winPageSize() + \sa pageLayout() */ void QPrinter::setWinPageSize(int pageSize) { @@ -1811,12 +1902,14 @@ void QPrinter::setWinPageSize(int pageSize) } /*! + \obsolete Use pageLayout.pageSize().windowsId() instead. + Returns the page size used by the printer under Windows. \warning This function is not portable so you may prefer to use paperSize() instead. - \sa setWinPageSize() + \sa pageLayout() */ int QPrinter::winPageSize() const { @@ -2148,13 +2241,19 @@ QPrinter::PrintRange QPrinter::printRange() const in the QPrinter::Point unit. \value PPK_PageMargins A QList containing the left, top, - right and bottom margin values. + right and bottom margin values in the QPrinter::Point unit. \value PPK_CopyCount An integer specifying the number of copies to print. \value PPK_SupportsMultipleCopies A boolean value indicating whether or not the printer supports printing multiple copies in one job. + \value PPK_QPageSize Set the page size using a QPageSize object. + + \value PPK_QPageMargins Set the page margins using a QPair of QMarginsF and QPageLayout::Unit. + + \value PPK_QPageLayout Set the page layout using a QPageLayout object. + \value PPK_CustomBase Basis for extension. */ @@ -2206,37 +2305,6 @@ QPrinter::PrintRange QPrinter::printRange() const Returns the current state of the printer being used by the print engine. */ -/* - Returns the dimensions for the given paper size, \a size, in millimeters. -*/ -QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size) -{ - if (size == QPrinter::Custom) return QSizeF(0, 0); - return QSizeF(qt_paperSizes[size][0], qt_paperSizes[size][1]); -} - -/* - Returns the PaperSize type that matches \a size, where \a size - is in millimeters. - - Because dimensions may not always be completely accurate (for - example when converting between units), a particular PaperSize - will be returned if it matches within -1/+1 millimeters. -*/ -QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size) -{ - for (int i = 0; i < static_cast(QPrinter::NPageSize); ++i) { - if (qt_paperSizes[i][0] >= size.width() - 1 && - qt_paperSizes[i][0] <= size.width() + 1 && - qt_paperSizes[i][1] >= size.height() - 1 && - qt_paperSizes[i][1] <= size.height() + 1) { - return QPrinter::PaperSize(i); - } - } - - return QPrinter::Custom; -} - QT_END_NAMESPACE #endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprinter.h b/src/printsupport/kernel/qprinter.h index f842c222f6..709d77d4e3 100644 --- a/src/printsupport/kernel/qprinter.h +++ b/src/printsupport/kernel/qprinter.h @@ -45,6 +45,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -60,6 +61,8 @@ class QPrinterPrivate; class QPaintEngine; class QPrintEngine; class QPrinterInfo; +class QPageSize; +class QPageMargins; class Q_PRINTSUPPORT_EXPORT QPrinter : public QPagedPaintDevice { @@ -304,6 +307,12 @@ public: void setCreator(const QString &); QString creator() const; + bool setPageLayout(const QPageLayout &pageLayout); + bool setPageSize(const QPageSize &pageSize); + bool setPageOrientation(QPageLayout::Orientation orientation); + bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units); + QPageLayout pageLayout() const; + void setOrientation(Orientation); Orientation orientation() const; diff --git a/src/printsupport/kernel/qprinter_p.h b/src/printsupport/kernel/qprinter_p.h index 2357b9e944..ddc2dad413 100644 --- a/src/printsupport/kernel/qprinter_p.h +++ b/src/printsupport/kernel/qprinter_p.h @@ -87,9 +87,7 @@ public: q_ptr(printer), printRange(QPrinter::AllPages), use_default_engine(true), - validPrinter(false), - hasCustomPageMargins(false), - hasUserSetPageSize(false) + validPrinter(false) { } @@ -129,7 +127,6 @@ public: uint validPrinter : 1; uint hasCustomPageMargins : 1; - uint hasUserSetPageSize : 1; // Used to remember which properties have been manually set by the user. QSet m_properties; -- cgit v1.2.3 From 1ffd79bfb7261268ea4b56d29122a48334a115a1 Mon Sep 17 00:00:00 2001 From: John Layt Date: Tue, 28 Jan 2014 15:05:17 +0100 Subject: QPrinter - Fix winPageSize() on Mac and Linux Using QPageSize internally provides the Windows ID on all platforms so remove the conditional compile on the QPrinter api and add support to the print engines. Change-Id: I31e23d5090a9b6ceb087c29dead050b0ee1855a5 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 11 ++++++----- src/plugins/printsupport/cups/qcupsprintengine.cpp | 3 +++ src/printsupport/kernel/qprintengine_pdf.cpp | 11 ++++++----- src/printsupport/kernel/qprinter.cpp | 8 -------- src/printsupport/kernel/qprinter.h | 2 -- 5 files changed, 15 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 95713eba59..fb968f31e9 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -472,8 +472,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va break; case PPK_SelectionOption: break; - case PPK_WindowsPageSize: - break; // The following keys are properties and settings that are supported by the Mac PrintEngine case PPK_Resolution: { @@ -535,6 +533,9 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va // Get the named page size from the printer if supported d->setPageSize(d->m_printDevice->supportedPageSize(value.toString())); break; + case PPK_WindowsPageSize: + d->setPageSize(QPageSize(QPageSize::id(value.toInt()))); + break; case PPK_PrinterName: { QString id = value.toString(); if (id.isEmpty()) @@ -629,9 +630,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const case PPK_SelectionOption: ret = QString(); break; - case PPK_WindowsPageSize: - // Special case, leave null - break; // The following keys are properties and settings that are supported by the Mac PrintEngine case PPK_CollateCopies: { @@ -680,6 +678,9 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const case PPK_PaperName: ret = d->m_pageLayout.pageSize().name(); break; + case PPK_WindowsPageSize: + ret = d->m_pageLayout.pageSize().windowsId(); + break; case PPK_PaperRect: // PaperRect is returned in device pixels ret = d->m_pageLayout.fullRectPixels(d->resolution.hRes); diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 90de1a2a8b..ec9963197c 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -83,6 +83,9 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v case PPK_PageSize: d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt()))); break; + case PPK_WindowsPageSize: + d->setPageSize(QPageSize(QPageSize::id(value.toInt()))); + break; case PPK_CustomPaperSize: d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); break; diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp index d62da0e1d6..a2ab68a96d 100644 --- a/src/printsupport/kernel/qprintengine_pdf.cpp +++ b/src/printsupport/kernel/qprintengine_pdf.cpp @@ -136,8 +136,6 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va // The following keys are settings that are unsupported by the PDF PrintEngine case PPK_CustomBase: break; - case PPK_WindowsPageSize: - break; // The following keys are properties and settings that are supported by the PDF PrintEngine case PPK_CollateCopies: @@ -188,6 +186,9 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va } break; } + case PPK_WindowsPageSize: + d->m_pageLayout.setPageSize(QPageSize(QPageSize::id(value.toInt()))); + break; case PPK_PaperSource: d->paperSource = QPrinter::PaperSource(value.toInt()); break; @@ -254,9 +255,6 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const case PPK_CustomBase: // Special case, leave null break; - case PPK_WindowsPageSize: - // Special case, leave null - break; // The following keys are properties and settings that are supported by the PDF PrintEngine case PPK_CollateCopies: @@ -298,6 +296,9 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const case PPK_PaperName: ret = d->m_pageLayout.pageSize().name(); break; + case PPK_WindowsPageSize: + ret = d->m_pageLayout.pageSize().windowsId(); + break; case PPK_PaperSource: ret = d->paperSource; break; diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index f72a0ae0fb..65dcf515b7 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -1882,16 +1882,12 @@ QPrintEngine *QPrinter::printEngine() const return d->printEngine; } -#if defined (Q_OS_WIN) /*! \obsolete Use QPageSize::id(windowsId) and setPageLayout(QPageSize) instead. Sets the page size to be used by the printer under Windows to \a pageSize. - \warning This function is not portable so you may prefer to use - setPaperSize() instead. - \sa pageLayout() */ void QPrinter::setWinPageSize(int pageSize) @@ -1906,9 +1902,6 @@ void QPrinter::setWinPageSize(int pageSize) Returns the page size used by the printer under Windows. - \warning This function is not portable so you may prefer to use - paperSize() instead. - \sa pageLayout() */ int QPrinter::winPageSize() const @@ -1916,7 +1909,6 @@ int QPrinter::winPageSize() const Q_D(const QPrinter); return d->printEngine->property(QPrintEngine::PPK_WindowsPageSize).toInt(); } -#endif // Q_OS_WIN /*! Returns a list of the resolutions (a list of dots-per-inch diff --git a/src/printsupport/kernel/qprinter.h b/src/printsupport/kernel/qprinter.h index 709d77d4e3..1f0639d81f 100644 --- a/src/printsupport/kernel/qprinter.h +++ b/src/printsupport/kernel/qprinter.h @@ -372,10 +372,8 @@ public: void setDoubleSidedPrinting(bool enable); bool doubleSidedPrinting() const; -#ifdef Q_OS_WIN void setWinPageSize(int winPageSize); int winPageSize() const; -#endif QRect paperRect() const; QRect pageRect() const; -- cgit v1.2.3 From 9393f744d4a5f7e056a4bf2ae1af8c951a4c8f18 Mon Sep 17 00:00:00 2001 From: John Layt Date: Sun, 12 Jan 2014 18:02:04 +0100 Subject: QPageSetupDialog - Use QPageLayout and QPageSize Convert the Linux / CUPS version of the QPageSetupDialog to use QPageSize and QPageLayout internally. As this is an almost complete re-write of the internals the liberty has been taken of doing renames and code moves that would normally be done in separate commits, but in this case would have been mostly pointless done separately. Change-Id: I6eaa7c1fbf0a04cb3425f1d322fcae89239e83b7 Reviewed-by: Lars Knoll --- src/printsupport/dialogs/qpagesetupdialog_unix.cpp | 684 ++++++++++----------- src/printsupport/dialogs/qpagesetupdialog_unix_p.h | 48 +- src/printsupport/dialogs/qpagesetupwidget.ui | 14 +- src/printsupport/dialogs/qprintdialog_unix.cpp | 19 +- 4 files changed, 356 insertions(+), 409 deletions(-) (limited to 'src') diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp index 7b84d8b86f..118d0c22c6 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp @@ -44,68 +44,25 @@ #ifndef QT_NO_PRINTDIALOG #include "qpagesetupdialog_unix_p.h" +#include +#include +#include + #include "qpainter.h" #include "qprintdialog.h" #include "qdialogbuttonbox.h" #include #include -#include -#include -#include -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) -# include -#endif +#include +#include QT_BEGIN_NAMESPACE -QSizeF qt_printerPaperSize(QPrinter::Orientation, QPrinter::PaperSize, QPrinter::Unit, int); - // Disabled until we have support for papersources on unix // #define PSD_ENABLE_PAPERSOURCE -static void populatePaperSizes(QComboBox* cb) -{ - cb->addItem(QPrintDialog::tr("A0"), QPrinter::A0); - cb->addItem(QPrintDialog::tr("A1"), QPrinter::A1); - cb->addItem(QPrintDialog::tr("A2"), QPrinter::A2); - cb->addItem(QPrintDialog::tr("A3"), QPrinter::A3); - cb->addItem(QPrintDialog::tr("A4"), QPrinter::A4); - cb->addItem(QPrintDialog::tr("A5"), QPrinter::A5); - cb->addItem(QPrintDialog::tr("A6"), QPrinter::A6); - cb->addItem(QPrintDialog::tr("A7"), QPrinter::A7); - cb->addItem(QPrintDialog::tr("A8"), QPrinter::A8); - cb->addItem(QPrintDialog::tr("A9"), QPrinter::A9); - cb->addItem(QPrintDialog::tr("B0"), QPrinter::B0); - cb->addItem(QPrintDialog::tr("B1"), QPrinter::B1); - cb->addItem(QPrintDialog::tr("B2"), QPrinter::B2); - cb->addItem(QPrintDialog::tr("B3"), QPrinter::B3); - cb->addItem(QPrintDialog::tr("B4"), QPrinter::B4); - cb->addItem(QPrintDialog::tr("B5"), QPrinter::B5); - cb->addItem(QPrintDialog::tr("B6"), QPrinter::B6); - cb->addItem(QPrintDialog::tr("B7"), QPrinter::B7); - cb->addItem(QPrintDialog::tr("B8"), QPrinter::B8); - cb->addItem(QPrintDialog::tr("B9"), QPrinter::B9); - cb->addItem(QPrintDialog::tr("B10"), QPrinter::B10); - cb->addItem(QPrintDialog::tr("C5E"), QPrinter::C5E); - cb->addItem(QPrintDialog::tr("DLE"), QPrinter::DLE); - cb->addItem(QPrintDialog::tr("Executive"), QPrinter::Executive); - cb->addItem(QPrintDialog::tr("Folio"), QPrinter::Folio); - cb->addItem(QPrintDialog::tr("Ledger"), QPrinter::Ledger); - cb->addItem(QPrintDialog::tr("Legal"), QPrinter::Legal); - cb->addItem(QPrintDialog::tr("Letter"), QPrinter::Letter); - cb->addItem(QPrintDialog::tr("Tabloid"), QPrinter::Tabloid); - cb->addItem(QPrintDialog::tr("US Common #10 Envelope"), QPrinter::Comm10E); - cb->addItem(QPrintDialog::tr("Custom"), QPrinter::Custom); -} - - -static QSizeF sizeForOrientation(QPrinter::Orientation orientation, const QSizeF &size) -{ - return (orientation == QPrinter::Portrait) ? size : QSizeF(size.height(), size.width()); -} - #ifdef PSD_ENABLE_PAPERSOURCE static const char *paperSourceNames[] = { "Only One", @@ -134,6 +91,10 @@ struct PaperSourceNames #endif +// QPagePreview +// - Private widget to display preview of page layout +// - Embedded in QPageSetupWidget + class QPagePreview : public QWidget { public: @@ -143,18 +104,9 @@ public: setMinimumSize(50, 50); } - void setPaperSize(const QSizeF& size) + void setPageLayout(const QPageLayout &layout) { - m_size = size; - update(); - } - - void setMargins(qreal left, qreal top, qreal right, qreal bottom) - { - m_left = left; - m_top = top; - m_right = right; - m_bottom = bottom; + m_pageLayout = layout; update(); } @@ -168,22 +120,19 @@ public: protected: void paintEvent(QPaintEvent *) { - QRect pageRect; - QSizeF adjustedSize(m_size); - adjustedSize.scale(width()-10, height()-10, Qt::KeepAspectRatio); - pageRect = QRect(QPoint(0,0), adjustedSize.toSize()); + QSize pageSize = m_pageLayout.fullRectPoints().size(); + QSizeF scaledSize = pageSize.scaled(width() - 10, height() - 10, Qt::KeepAspectRatio); + QRect pageRect = QRect(QPoint(0,0), scaledSize.toSize()); pageRect.moveCenter(rect().center()); - - qreal width_factor = pageRect.width() / m_size.width(); - qreal height_factor = pageRect.height() / m_size.height(); - int leftSize = qRound(m_left*width_factor); - int topSize = qRound(m_top*height_factor); - int rightSize = qRound(m_right*width_factor); - int bottomSize = qRound(m_bottom * height_factor); - QRect marginRect(pageRect.x()+leftSize, - pageRect.y()+topSize, - pageRect.width() - (leftSize+rightSize+1), - pageRect.height() - (topSize+bottomSize+1)); + qreal width_factor = scaledSize.width() / pageSize.width(); + qreal height_factor = scaledSize.height() / pageSize.height(); + QMarginsF margins = m_pageLayout.margins(QPageLayout::Point); + int left = qRound(margins.left() * width_factor); + int top = qRound(margins.top() * height_factor); + int right = qRound(margins.right() * width_factor); + int bottom = qRound(margins.bottom() * height_factor); + QRect marginRect(pageRect.x() + left, pageRect.y() + top, + pageRect.width() - (left + right + 1), pageRect.height() - (top + bottom + 1)); QPainter p(this); QColor shadow(palette().mid().color()); @@ -226,14 +175,17 @@ protected: } private: - // all these are in points - qreal m_left, m_top, m_right, m_bottom; - // specify width / height of one page in preview + // Page Layout + QPageLayout m_pageLayout; + // Pages Per Sheet / n-up layout int m_pagePreviewColumns, m_pagePreviewRows; - QSizeF m_size; }; +// QUnixPageSetupDialogPrivate +// - Linux / Cups implementation of QPageSetupDialogPrivate +// - Embeds QPageSetupWidget + class QUnixPageSetupDialogPrivate : public QPageSetupDialogPrivate { Q_DECLARE_PUBLIC(QPageSetupDialog) @@ -272,27 +224,24 @@ void QUnixPageSetupDialogPrivate::init() lay->addWidget(buttons); } +// QPageSetupWidget +// - Private widget implementation for Linux / CUPS +// - Embeds QPagePreview +// - TODO Could be made public as a stand-alone widget? + QPageSetupWidget::QPageSetupWidget(QWidget *parent) : QWidget(parent), - m_printer(0), - m_blockSignals(false), - m_cups(false) + m_pagePreview(0), + m_printer(0), + m_outputFormat(QPrinter::PdfFormat), + m_units(QPageLayout::Point), + m_blockSignals(false) { - widget.setupUi(this); - - QString suffix = (QLocale::system().measurementSystem() == QLocale::ImperialSystem) - ? QString::fromLatin1(" in") - : QString::fromLatin1(" mm"); - widget.topMargin->setSuffix(suffix); - widget.bottomMargin->setSuffix(suffix); - widget.leftMargin->setSuffix(suffix); - widget.rightMargin->setSuffix(suffix); - widget.paperWidth->setSuffix(suffix); - widget.paperHeight->setSuffix(suffix); - - QVBoxLayout *lay = new QVBoxLayout(widget.preview); - widget.preview->setLayout(lay); - m_pagePreview = new QPagePreview(widget.preview); + m_ui.setupUi(this); + + QVBoxLayout *lay = new QVBoxLayout(m_ui.preview); + m_ui.preview->setLayout(lay); + m_pagePreview = new QPagePreview(m_ui.preview); m_pagePreview->setPagePreviewLayout(1, 1); lay->addWidget(m_pagePreview); @@ -301,242 +250,302 @@ QPageSetupWidget::QPageSetupWidget(QWidget *parent) #ifdef PSD_ENABLE_PAPERSOURCE for (int i=0; paperSourceNames[i]; ++i) - widget.paperSource->insertItem(paperSourceNames[i]); + m_ui.paperSource->insertItem(paperSourceNames[i]); #else - widget.paperSourceLabel->setVisible(false); - widget.paperSource->setVisible(false); + m_ui.paperSourceLabel->setVisible(false); + m_ui.paperSource->setVisible(false); #endif - widget.reverseLandscape->setVisible(false); - widget.reversePortrait->setVisible(false); + m_ui.reverseLandscape->setVisible(false); + m_ui.reversePortrait->setVisible(false); - populatePaperSizes(widget.paperSize); + initUnits(); initPagesPerSheet(); - QStringList units; - units << tr("Centimeters (cm)") << tr("Millimeters (mm)") << tr("Inches (in)") << tr("Points (pt)"); - widget.unit->addItems(units); - connect(widget.unit, SIGNAL(activated(int)), this, SLOT(unitChanged(int))); - widget.unit->setCurrentIndex((QLocale::system().measurementSystem() == QLocale::ImperialSystem) ? 2 : 1); - connect(widget.paperSize, SIGNAL(currentIndexChanged(int)), this, SLOT(_q_paperSizeChanged())); - connect(widget.paperWidth, SIGNAL(valueChanged(double)), this, SLOT(_q_paperSizeChanged())); - connect(widget.paperHeight, SIGNAL(valueChanged(double)), this, SLOT(_q_paperSizeChanged())); + connect(m_ui.unitCombo, SIGNAL(activated(int)), this, SLOT(unitChanged())); + + connect(m_ui.pageSizeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(pageSizeChanged())); + connect(m_ui.pageWidth, SIGNAL(valueChanged(double)), this, SLOT(pageSizeChanged())); + connect(m_ui.pageHeight, SIGNAL(valueChanged(double)), this, SLOT(pageSizeChanged())); - connect(widget.leftMargin, SIGNAL(valueChanged(double)), this, SLOT(setLeftMargin(double))); - connect(widget.topMargin, SIGNAL(valueChanged(double)), this, SLOT(setTopMargin(double))); - connect(widget.rightMargin, SIGNAL(valueChanged(double)), this, SLOT(setRightMargin(double))); - connect(widget.bottomMargin, SIGNAL(valueChanged(double)), this, SLOT(setBottomMargin(double))); + connect(m_ui.leftMargin, SIGNAL(valueChanged(double)), this, SLOT(leftMarginChanged(double))); + connect(m_ui.topMargin, SIGNAL(valueChanged(double)), this, SLOT(topMarginChanged(double))); + connect(m_ui.rightMargin, SIGNAL(valueChanged(double)), this, SLOT(rightMarginChanged(double))); + connect(m_ui.bottomMargin, SIGNAL(valueChanged(double)), this, SLOT(bottomMarginChanged(double))); - connect(widget.portrait, SIGNAL(clicked()), this, SLOT(_q_pageOrientationChanged())); - connect(widget.landscape, SIGNAL(clicked()), this, SLOT(_q_pageOrientationChanged())); - connect(widget.pagesPerSheetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_q_pagesPerSheetChanged())); + connect(m_ui.portrait, SIGNAL(clicked()), this, SLOT(pageOrientationChanged())); + connect(m_ui.landscape, SIGNAL(clicked()), this, SLOT(pageOrientationChanged())); + connect(m_ui.pagesPerSheetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(pagesPerSheetChanged())); } -void QPageSetupWidget::setPrinter(QPrinter *printer) +// Init the Units combo box +void QPageSetupWidget::initUnits() { - m_printer = printer; - m_blockSignals = true; - selectPdfPsPrinter(printer); - printer->getPageMargins(&m_leftMargin, &m_topMargin, &m_rightMargin, &m_bottomMargin, QPrinter::Point); - unitChanged(widget.unit->currentIndex()); - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); - m_paperSize = printer->paperSize(QPrinter::Point); - widget.paperWidth->setValue(m_paperSize.width() / m_currentMultiplier); - widget.paperHeight->setValue(m_paperSize.height() / m_currentMultiplier); - - widget.landscape->setChecked(printer->orientation() == QPrinter::Landscape); + m_ui.unitCombo->addItem(tr("Millimeters (mm)"), QVariant::fromValue(QPageLayout::Millimeter)); + m_ui.unitCombo->addItem(tr("Inches (in)"), QVariant::fromValue(QPageLayout::Inch)); + m_ui.unitCombo->addItem(tr("Points (pt)"), QVariant::fromValue(QPageLayout::Point)); + m_ui.unitCombo->addItem(tr("Pica (P̸)"), QVariant::fromValue(QPageLayout::Pica)); + m_ui.unitCombo->addItem(tr("Didot (DD)"), QVariant::fromValue(QPageLayout::Didot)); + m_ui.unitCombo->addItem(tr("Cicero (CC)"), QVariant::fromValue(QPageLayout::Cicero)); + + // Initailly default to locale measurement system, mm if metric, in otherwise + m_ui.unitCombo->setCurrentIndex(QLocale().measurementSystem() != QLocale::MetricSystem); +} -#ifdef PSD_ENABLE_PAPERSOURCE - widget.paperSource->setCurrentItem(printer->paperSource()); +// Init the Pages Per Sheet (n-up) combo boxes if using CUPS +void QPageSetupWidget::initPagesPerSheet() +{ +#if !defined(QT_NO_CUPS) + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Top to Bottom"), + QVariant::fromValue(QCUPSSupport::LeftToRightTopToBottom)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Bottom to Top"), + QVariant::fromValue(QCUPSSupport::LeftToRightBottomToTop)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Bottom to Top"), + QVariant::fromValue(QCUPSSupport::RightToLeftBottomToTop)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Top to Bottom"), + QVariant::fromValue(QCUPSSupport::RightToLeftTopToBottom)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Left to Right"), + QVariant::fromValue(QCUPSSupport::BottomToTopLeftToRight)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Right to Left"), + QVariant::fromValue(QCUPSSupport::BottomToTopRightToLeft)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Left to Right"), + QVariant::fromValue(QCUPSSupport::TopToBottomLeftToRight)); + m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Right to Left"), + QVariant::fromValue(QCUPSSupport::TopToBottomRightToLeft)); + + m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("1 (1x1)"), + QVariant::fromValue(QCUPSSupport::OnePagePerSheet)); + m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("2 (2x1)"), + QVariant::fromValue(QCUPSSupport::TwoPagesPerSheet)); + m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("4 (2x2)"), + QVariant::fromValue(QCUPSSupport::FourPagesPerSheet)); + m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("6 (2x3)"), + QVariant::fromValue(QCUPSSupport::SixPagesPerSheet)); + m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("9 (3x3)"), + QVariant::fromValue(QCUPSSupport::NinePagesPerSheet)); + m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("16 (4x4)"), + QVariant::fromValue(QCUPSSupport::SixteenPagesPerSheet)); + + // Set to QCUPSSupport::OnePagePerSheet + m_ui.pagesPerSheetCombo->setCurrentIndex(0); + // Set to QCUPSSupport::LeftToRightTopToBottom + m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(0); +#else + // Disable if CUPS wasn't found + m_ui.pagesPerSheetButtonGroup->hide(); #endif - Q_ASSERT(m_blockSignals); - m_blockSignals = false; - _q_paperSizeChanged(); } -// set gui data on printer -void QPageSetupWidget::setupPrinter() const +void QPageSetupWidget::initPageSizes() { - QPrinter::Orientation orientation = widget.portrait->isChecked() - ? QPrinter::Portrait - : QPrinter::Landscape; - m_printer->setOrientation(orientation); - // paper format - QVariant val = widget.paperSize->itemData(widget.paperSize->currentIndex()); - int ps = m_printer->pageSize(); - if (val.type() == QVariant::Int) { - ps = val.toInt(); - } -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - else if (val.type() == QVariant::ByteArray) { - for (int papersize = 0; papersize < QPrinter::NPageSize; ++papersize) { - QSize size = QPageSize(QPageSize::PageSizeId(papersize)).sizePoints(); - if (size.width() == m_paperSize.width() && size.height() == m_paperSize.height()) { - ps = static_cast(papersize); - break; + m_blockSignals = true; + + m_ui.pageSizeCombo->clear(); + + if (m_outputFormat == QPrinter::NativeFormat && !m_printerName.isEmpty()) { + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) { + QPrintDevice printDevice = ps->createPrintDevice(m_printerName); + foreach (const QPageSize &pageSize, printDevice.supportedPageSizes()) { + m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize.id())); + } + if (m_ui.pageSizeCombo->count() > 0 && printDevice.supportsCustomPageSizes()) { + m_ui.pageSizeCombo->addItem(tr("Custom"), QVariant::fromValue(QPageSize::Custom)); + m_blockSignals = false; + return; } } } -#endif - if (ps == QPrinter::Custom) { - m_printer->setPaperSize(sizeForOrientation(orientation, m_paperSize), QPrinter::Point); - } - else { - m_printer->setPaperSize(static_cast(ps)); - } - m_printer->setPaperName(widget.paperSize->currentText()); -#ifdef PSD_ENABLE_PAPERSOURCE - m_printer->setPaperSource((QPrinter::PaperSource)widget.paperSource->currentIndex()); -#endif - m_printer->setPageMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin, QPrinter::Point); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - QCUPSSupport::PagesPerSheet pagesPerSheet = widget.pagesPerSheetCombo->currentData() - .value(); - QCUPSSupport::PagesPerSheetLayout pagesPerSheetLayout = widget.pagesPerSheetLayoutCombo->currentData() - .value(); + // If PdfFormat or no available printer page sizes, populate with all page sizes + for (int id = 0; id < QPageSize::LastPageSize; ++id) { + if (QPageSize::PageSizeId(id) == QPageSize::Custom) { + m_ui.pageSizeCombo->addItem(tr("Custom"), id); + } else { + QPageSize pageSize = QPageSize(QPageSize::PageSizeId(id)); + m_ui.pageSizeCombo->addItem(pageSize.name(), id); + } + } - QCUPSSupport::setPagesPerSheetLayout(m_printer, pagesPerSheet, pagesPerSheetLayout); -#endif + m_blockSignals = false; } -void QPageSetupWidget::selectPrinter() +// Set the dialog to use the given QPrinter +// Usually only called on first creation +void QPageSetupWidget::setPrinter(QPrinter *printer) { - widget.paperSize->clear(); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - if (QCUPSSupport::isAvailable()) { - m_cups = true; - QCUPSSupport cups; - cups.setCurrentPrinter(m_printer->printerName()); - const ppd_option_t* pageSizes = cups.pageSizes(); - const int numChoices = pageSizes ? pageSizes->num_choices : 0; - - int cupsDefaultSize = 0; - QSize qtPreferredSize = m_printer->paperSize(QPrinter::Point).toSize(); - QString qtPaperName = m_printer->paperName(); - bool preferredSizeMatched = false; - for (int i = 0; i < numChoices; ++i) { - widget.paperSize->addItem(QString::fromLocal8Bit(pageSizes->choices[i].text), QByteArray(pageSizes->choices[i].choice)); - if (static_cast(pageSizes->choices[i].marked) == 1) - cupsDefaultSize = i; - if (qtPaperName == QString::fromLocal8Bit(pageSizes->choices[i].text)) { - widget.paperSize->setCurrentIndex(i); - preferredSizeMatched = true; - } else { - QRect cupsPaperSize = cups.paperRect(pageSizes->choices[i].choice); - QSize diff = cupsPaperSize.size() - qtPreferredSize; - if (qAbs(diff.width()) < 5 && qAbs(diff.height()) < 5) { - widget.paperSize->setCurrentIndex(i); - preferredSizeMatched = true; - } - } - } - if (!preferredSizeMatched) - widget.paperSize->setCurrentIndex(cupsDefaultSize); - m_printer->getPageMargins(&m_leftMargin, &m_topMargin, &m_rightMargin, &m_bottomMargin, QPrinter::Point); - } else - m_cups = false; -#endif - if (widget.paperSize->count() == 0) { - populatePaperSizes(widget.paperSize); - widget.paperSize->setCurrentIndex(widget.paperSize->findData( - QLocale::system().measurementSystem() == QLocale::ImperialSystem ? QPrinter::Letter : QPrinter::A4)); + m_printer = printer; + + // Initialize the layout to the current QPrinter layout + m_pageLayout = m_printer->pageLayout(); + // Assume if margins are Points then is by default, so set to locale default units + if (m_pageLayout.units() == QPageLayout::Point) { + if (QLocale().measurementSystem() == QLocale::MetricSystem) + m_pageLayout.setUnits(QPageLayout::Millimeter); + else + m_pageLayout.setUnits(QPageLayout::Inch); } + m_units = m_pageLayout.units(); + m_pagePreview->setPageLayout(m_pageLayout); - unitChanged(widget.unit->currentIndex()); - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); + // Then update the widget with the current printer details + selectPrinter(m_printer->outputFormat(), m_printer->printerName()); } -void QPageSetupWidget::selectPdfPsPrinter(const QPrinter *p) +// The printer selected in the QPrintDialog has been changed, update the widget to reflect this +// Note the QPrinter is not updated at this time in case the user presses the Cancel button in QPrintDialog +void QPageSetupWidget::selectPrinter(QPrinter::OutputFormat outputFormat, const QString &printerName) { - m_cups = false; - widget.paperSize->clear(); - populatePaperSizes(widget.paperSize); - widget.paperSize->setCurrentIndex(widget.paperSize->findData(p->paperSize())); - unitChanged(widget.unit->currentIndex()); - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); + m_outputFormat = outputFormat; + m_printerName = printerName; + initPageSizes(); + updateWidget(); } -// Updates size/preview after the combobox has been changed. -void QPageSetupWidget::_q_paperSizeChanged() +// Update the widget with the current settings +// TODO Break up into more intelligent chunks? +void QPageSetupWidget::updateWidget() { - if (m_blockSignals) return; m_blockSignals = true; - bool custom = false; - QVariant val = widget.paperSize->itemData(widget.paperSize->currentIndex()); - QPrinter::Orientation orientation = widget.portrait->isChecked() ? QPrinter::Portrait : QPrinter::Landscape; - - if (m_cups) { - // OutputFormat == NativeFormat, data is QString Cups paper name - QByteArray cupsPageSize = val.toByteArray(); - custom = (cupsPageSize == QByteArrayLiteral("Custom")); -#ifndef QT_NO_CUPS - if (!custom) { - QCUPSSupport cups; - cups.setCurrentPrinter(m_printer->printerName()); - m_paperSize = sizeForOrientation(orientation, cups.paperRect(cupsPageSize).size()); - } -#endif - } else { - // OutputFormat == PdfFormat, data is QPrinter::PageSize - QPrinter::PaperSize size = QPrinter::PaperSize(val.toInt()); - custom = size == QPrinter::Custom; - if (!custom) - m_paperSize = qt_printerPaperSize(orientation, size, QPrinter::Point, 1); + QString suffix; + switch (m_units) { + case QPageLayout::Millimeter: + suffix = tr("mm"); + break; + case QPageLayout::Point: + suffix = tr("pt"); + break; + case QPageLayout::Inch: + suffix = tr("in"); + break; + case QPageLayout::Pica: + suffix = tr("P̸"); + break; + case QPageLayout::Didot: + suffix = tr("DD"); + break; + case QPageLayout::Cicero: + suffix = tr("CC"); + break; } - if (custom) { - // Convert input custom size Units to Points - m_paperSize = QSizeF(widget.paperWidth->value() * m_currentMultiplier, - widget.paperHeight->value() * m_currentMultiplier); + m_ui.unitCombo->setCurrentIndex(m_ui.unitCombo->findData(QVariant::fromValue(m_units))); + + m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(m_pageLayout.pageSize().id()))); + + QMarginsF min; + QMarginsF max; + + if (m_pageLayout.mode() == QPageLayout::FullPageMode) { + min = QMarginsF(0.0, 0.0, 0.0, 0.0); + max = QMarginsF(9999.9999, 9999.9999, 9999.9999, 9999.9999); } else { - // Display standard size Points as Units - widget.paperWidth->setValue(m_paperSize.width() / m_currentMultiplier); - widget.paperHeight->setValue(m_paperSize.height() / m_currentMultiplier); + min = m_pageLayout.minimumMargins(); + max = m_pageLayout.maximumMargins(); } - m_pagePreview->setPaperSize(m_paperSize); + m_ui.leftMargin->setSuffix(suffix); + m_ui.leftMargin->setMinimum(min.left()); + m_ui.leftMargin->setMaximum(max.left()); + m_ui.leftMargin->setValue(m_pageLayout.margins().left()); + + m_ui.rightMargin->setSuffix(suffix); + m_ui.rightMargin->setMinimum(min.right()); + m_ui.rightMargin->setMaximum(max.right()); + m_ui.rightMargin->setValue(m_pageLayout.margins().right()); + + m_ui.topMargin->setSuffix(suffix); + m_ui.topMargin->setMinimum(min.top()); + m_ui.topMargin->setMaximum(max.top()); + m_ui.topMargin->setValue(m_pageLayout.margins().top()); + + m_ui.bottomMargin->setSuffix(suffix); + m_ui.bottomMargin->setMinimum(min.bottom()); + m_ui.bottomMargin->setMaximum(max.bottom()); + m_ui.bottomMargin->setValue(m_pageLayout.margins().bottom()); - widget.paperWidth->setEnabled(custom); - widget.paperHeight->setEnabled(custom); - widget.widthLabel->setEnabled(custom); - widget.heightLabel->setEnabled(custom); + bool isCustom = m_ui.pageSizeCombo->currentData().value() == QPageSize::Custom; + + m_ui.pageWidth->setSuffix(suffix); + m_ui.pageWidth->setValue(m_pageLayout.fullRect(m_units).width()); + m_ui.pageWidth->setEnabled(isCustom); + m_ui.widthLabel->setEnabled(isCustom); + + m_ui.pageHeight->setSuffix(suffix); + m_ui.pageHeight->setValue(m_pageLayout.fullRect(m_units).height()); + m_ui.pageHeight->setEnabled(isCustom); + m_ui.heightLabel->setEnabled(isCustom); + + m_ui.landscape->setChecked(m_pageLayout.orientation() == QPageLayout::Landscape); + + m_ui.pagesPerSheetButtonGroup->setEnabled(m_outputFormat == QPrinter::NativeFormat); + +#ifdef PSD_ENABLE_PAPERSOURCE + m_ui.paperSource->setCurrentItem(printer->paperSource()); +#endif m_blockSignals = false; } -void QPageSetupWidget::_q_pageOrientationChanged() +// Set the dialog chosen options on the QPrinter +// Normally only called when the QPrintDialog or QPageSetupDialog OK button is pressed +void QPageSetupWidget::setupPrinter() const { - bool custom = false; - QVariant val = widget.paperSize->itemData(widget.paperSize->currentIndex()); + m_printer->setPageLayout(m_pageLayout); +#if !defined(QT_NO_CUPS) + QCUPSSupport::PagesPerSheet pagesPerSheet = m_ui.pagesPerSheetCombo->currentData() + .value(); + QCUPSSupport::PagesPerSheetLayout pagesPerSheetLayout = m_ui.pagesPerSheetLayoutCombo->currentData() + .value(); + QCUPSSupport::setPagesPerSheetLayout(m_printer, pagesPerSheet, pagesPerSheetLayout); +#endif +#ifdef PSD_ENABLE_PAPERSOURCE + m_printer->setPaperSource((QPrinter::PaperSource)m_ui.paperSource->currentIndex()); +#endif +} - if (m_cups) { - // OutputFormat == NativeFormat, data is QString Cups paper name - QByteArray cupsPageSize = val.toByteArray(); - custom = (cupsPageSize == QByteArrayLiteral("Custom")); +// Updates size/preview after the combobox has been changed. +void QPageSetupWidget::pageSizeChanged() +{ + if (m_blockSignals) + return; + + QPageSize::PageSizeId id = m_ui.pageSizeCombo->currentData().value(); + if (id != QPageSize::Custom) { + // TODO Set layout margin min/max to printer custom min/max + m_pageLayout.setPageSize(QPageSize(id)); } else { - // OutputFormat == PdfFormat, data is QPrinter::PageSize - QPrinter::PaperSize size = QPrinter::PaperSize(val.toInt()); - custom = size == QPrinter::Custom; + QSizeF customSize; + if (m_pageLayout.orientation() == QPageLayout::Landscape) + customSize = QSizeF(m_ui.pageHeight->value(), m_ui.pageWidth->value()); + else + customSize = QSizeF(m_ui.pageWidth->value(), m_ui.pageHeight->value()); + // TODO Set layout margin min/max to printer min/max for page size + m_pageLayout.setPageSize(QPageSize(customSize, QPageSize::Unit(m_units))); } + m_pagePreview->setPageLayout(m_pageLayout); - if (custom) { - double tmp = widget.paperWidth->value(); - widget.paperWidth->setValue(widget.paperHeight->value()); - widget.paperHeight->setValue(tmp); - } - _q_paperSizeChanged(); + updateWidget(); } -void QPageSetupWidget::_q_pagesPerSheetChanged() +void QPageSetupWidget::pageOrientationChanged() { -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - QCUPSSupport::PagesPerSheet pagesPerSheet = widget.pagesPerSheetCombo->currentData() - .value(); + if (m_blockSignals) + return; + m_pageLayout.setOrientation(m_ui.portrait->isChecked() ? QPageLayout::Portrait : QPageLayout::Landscape); + m_pagePreview->setPageLayout(m_pageLayout); + updateWidget(); +} - switch (pagesPerSheet) { +void QPageSetupWidget::pagesPerSheetChanged() +{ +#if !defined(QT_NO_CUPS) + switch (m_ui.pagesPerSheetCombo->currentData().toInt()) { + case QCUPSSupport::OnePagePerSheet: + m_pagePreview->setPagePreviewLayout(1, 1); + break; case QCUPSSupport::TwoPagesPerSheet: m_pagePreview->setPagePreviewLayout(1, 2); break; @@ -552,84 +561,53 @@ void QPageSetupWidget::_q_pagesPerSheetChanged() case QCUPSSupport::SixteenPagesPerSheet: m_pagePreview->setPagePreviewLayout(4, 4); break; - case QCUPSSupport::OnePagePerSheet: - default: - m_pagePreview->setPagePreviewLayout(1, 1); - break; } #endif } -extern double qt_multiplierForUnit(QPrinter::Unit unit, int resolution); - -void QPageSetupWidget::unitChanged(int item) +void QPageSetupWidget::unitChanged() { - QString suffix; - switch(item) { - case 0: - m_currentMultiplier = 10 * qt_multiplierForUnit(QPrinter::Millimeter, 1); - suffix = QString::fromLatin1(" cm"); - break; - case 2: - m_currentMultiplier = qt_multiplierForUnit(QPrinter::Inch, 1); - suffix = QString::fromLatin1(" in"); - break; - case 3: - m_currentMultiplier = qt_multiplierForUnit(QPrinter::Point, 1); - suffix = QString::fromLatin1(" pt"); - break; - case 1: - default: - m_currentMultiplier = qt_multiplierForUnit(QPrinter::Millimeter, 1); - suffix = QString::fromLatin1(" mm"); - break; - } - const bool old = m_blockSignals; - m_blockSignals = true; - widget.topMargin->setSuffix(suffix); - widget.leftMargin->setSuffix(suffix); - widget.rightMargin->setSuffix(suffix); - widget.bottomMargin->setSuffix(suffix); - widget.paperWidth->setSuffix(suffix); - widget.paperHeight->setSuffix(suffix); - widget.topMargin->setValue(m_topMargin / m_currentMultiplier); - widget.leftMargin->setValue(m_leftMargin / m_currentMultiplier); - widget.rightMargin->setValue(m_rightMargin / m_currentMultiplier); - widget.bottomMargin->setValue(m_bottomMargin / m_currentMultiplier); - widget.paperWidth->setValue(m_paperSize.width() / m_currentMultiplier); - widget.paperHeight->setValue(m_paperSize.height() / m_currentMultiplier); - m_blockSignals = old; + if (m_blockSignals) + return; + m_units = m_ui.unitCombo->currentData().value(); + m_pageLayout.setUnits(m_units); + updateWidget(); } -void QPageSetupWidget::setTopMargin(double newValue) +void QPageSetupWidget::topMarginChanged(double newValue) { - if (m_blockSignals) return; - m_topMargin = newValue * m_currentMultiplier; - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); + if (m_blockSignals) + return; + m_pageLayout.setTopMargin(newValue); + m_pagePreview->setPageLayout(m_pageLayout); } -void QPageSetupWidget::setBottomMargin(double newValue) +void QPageSetupWidget::bottomMarginChanged(double newValue) { - if (m_blockSignals) return; - m_bottomMargin = newValue * m_currentMultiplier; - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); + if (m_blockSignals) + return; + m_pageLayout.setBottomMargin(newValue); + m_pagePreview->setPageLayout(m_pageLayout); } -void QPageSetupWidget::setLeftMargin(double newValue) +void QPageSetupWidget::leftMarginChanged(double newValue) { - if (m_blockSignals) return; - m_leftMargin = newValue * m_currentMultiplier; - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); + if (m_blockSignals) + return; + m_pageLayout.setLeftMargin(newValue); + m_pagePreview->setPageLayout(m_pageLayout); } -void QPageSetupWidget::setRightMargin(double newValue) +void QPageSetupWidget::rightMarginChanged(double newValue) { - if (m_blockSignals) return; - m_rightMargin = newValue * m_currentMultiplier; - m_pagePreview->setMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin); + if (m_blockSignals) + return; + m_pageLayout.setRightMargin(newValue); + m_pagePreview->setPageLayout(m_pageLayout); } - +// QPageSetupDialog +// - Public Linux / CUPS class implementation QPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent) : QDialog(*(new QUnixPageSetupDialogPrivate(printer)), parent) @@ -639,7 +617,6 @@ QPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent) static_cast(d)->init(); } - QPageSetupDialog::QPageSetupDialog(QWidget *parent) : QDialog(*(new QUnixPageSetupDialogPrivate(0)), parent) { @@ -658,35 +635,6 @@ int QPageSetupDialog::exec() return ret; } -void QPageSetupWidget::initPagesPerSheet() -{ -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Top to Bottom"), QVariant::fromValue(QCUPSSupport::LeftToRightTopToBottom)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Bottom to Top"), QVariant::fromValue(QCUPSSupport::LeftToRightBottomToTop)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Bottom to Top"), QVariant::fromValue(QCUPSSupport::RightToLeftBottomToTop)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Top to Bottom"), QVariant::fromValue(QCUPSSupport::RightToLeftTopToBottom)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Left to Right"), QVariant::fromValue(QCUPSSupport::BottomToTopLeftToRight)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Right to Left"), QVariant::fromValue(QCUPSSupport::BottomToTopRightToLeft)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Left to Right"), QVariant::fromValue(QCUPSSupport::TopToBottomLeftToRight)); - widget.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Right to Left"), QVariant::fromValue(QCUPSSupport::TopToBottomRightToLeft)); - - widget.pagesPerSheetCombo->addItem(QPrintDialog::tr("1 (1x1)"), QVariant::fromValue(QCUPSSupport::OnePagePerSheet)); - widget.pagesPerSheetCombo->addItem(QPrintDialog::tr("2 (2x1)"), QVariant::fromValue(QCUPSSupport::TwoPagesPerSheet)); - widget.pagesPerSheetCombo->addItem(QPrintDialog::tr("4 (2x2)"), QVariant::fromValue(QCUPSSupport::FourPagesPerSheet)); - widget.pagesPerSheetCombo->addItem(QPrintDialog::tr("6 (2x3)"), QVariant::fromValue(QCUPSSupport::SixPagesPerSheet)); - widget.pagesPerSheetCombo->addItem(QPrintDialog::tr("9 (3x3)"), QVariant::fromValue(QCUPSSupport::NinePagesPerSheet)); - widget.pagesPerSheetCombo->addItem(QPrintDialog::tr("16 (4x4)"), QVariant::fromValue(QCUPSSupport::SixteenPagesPerSheet)); - - // Set the combo to "1 (1x1)" -- QCUPSSupport::OnePagePerSheet - widget.pagesPerSheetCombo->setCurrentIndex(0); - // Set the layout combo to QCUPSSupport::LeftToRightTopToBottom - widget.pagesPerSheetLayoutCombo->setCurrentIndex(0); -#else - // Disable if CUPS wasn't found - widget.pagesPerSheetButtonGroup->hide(); -#endif -} - QT_END_NAMESPACE #include "moc_qpagesetupdialog.cpp" diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h index 4245c3ae5f..2a359a8118 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h +++ b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h @@ -57,6 +57,10 @@ #ifndef QT_NO_PRINTDIALOG +#include "qprinter.h" + +#include + #include QT_BEGIN_NAMESPACE @@ -69,37 +73,37 @@ class QPageSetupWidget : public QWidget { public: explicit QPageSetupWidget(QWidget *parent = 0); explicit QPageSetupWidget(QPrinter *printer, QWidget *parent = 0); + void setPrinter(QPrinter *printer); - /// copy information from the widget and apply that to the printer. + void selectPrinter(QPrinter::OutputFormat outputFormat, const QString &printerName); void setupPrinter() const; - void selectPrinter(); - void selectPdfPsPrinter(const QPrinter *p); private slots: - void _q_pageOrientationChanged(); - void _q_paperSizeChanged(); - void _q_pagesPerSheetChanged(); - void unitChanged(int item); - void setTopMargin(double newValue); - void setBottomMargin(double newValue); - void setLeftMargin(double newValue); - void setRightMargin(double newValue); + void pageSizeChanged(); + void pageOrientationChanged(); + void pagesPerSheetChanged(); + void unitChanged(); + void topMarginChanged(double newValue); + void bottomMarginChanged(double newValue); + void leftMarginChanged(double newValue); + void rightMarginChanged(double newValue); private: - friend class QUnixPrintWidgetPrivate; - Ui::QPageSetupWidget widget; + friend class QUnixPrintWidgetPrivate; // Needed by checkFields() + + void updateWidget(); + void initUnits(); + void initPagesPerSheet(); + void initPageSizes(); + + Ui::QPageSetupWidget m_ui; QPagePreview *m_pagePreview; QPrinter *m_printer; - qreal m_leftMargin; - qreal m_topMargin; - qreal m_rightMargin; - qreal m_bottomMargin; - QSizeF m_paperSize; // In QPrinter::Point - qreal m_currentMultiplier; + QPrinter::OutputFormat m_outputFormat; + QString m_printerName; + QPageLayout m_pageLayout; + QPageLayout::Unit m_units; bool m_blockSignals; - bool m_cups; - - void initPagesPerSheet(); }; QT_END_NAMESPACE diff --git a/src/printsupport/dialogs/qpagesetupwidget.ui b/src/printsupport/dialogs/qpagesetupwidget.ui index ffd2650f4c..960a9dac17 100644 --- a/src/printsupport/dialogs/qpagesetupwidget.ui +++ b/src/printsupport/dialogs/qpagesetupwidget.ui @@ -28,12 +28,12 @@ Page size: - paperSize + pageSizeCombo - + @@ -41,14 +41,14 @@ Width: - paperWidth + pageWidth - + 9999.989999999999782 @@ -60,12 +60,12 @@ Height: - paperHeight + pageHeight - + 9999.989999999999782 @@ -105,7 +105,7 @@ - + diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index 2ec1088bb4..e8f959bcd5 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -120,8 +120,7 @@ public: QPrintPropertiesDialog(QAbstractPrintDialog *parent = 0); ~QPrintPropertiesDialog(); - void selectPrinter(); - void selectPdfPsPrinter(const QPrinter *p); + void selectPrinter(QPrinter::OutputFormat outputFormat, const QString &printerName); /// copy printer properties to the widget void applyPrinterProperties(QPrinter *p); @@ -281,14 +280,9 @@ void QPrintPropertiesDialog::setupPrinter() const #endif } -void QPrintPropertiesDialog::selectPrinter() +void QPrintPropertiesDialog::selectPrinter(QPrinter::OutputFormat outputFormat, const QString &printerName) { - widget.pageSetup->selectPrinter(); -} - -void QPrintPropertiesDialog::selectPdfPsPrinter(const QPrinter *p) -{ - widget.pageSetup->selectPdfPsPrinter(p); + widget.pageSetup->selectPrinter(outputFormat, printerName); } void QPrintPropertiesDialog::showEvent(QShowEvent* event) @@ -886,7 +880,8 @@ bool QUnixPrintWidgetPrivate::checkFields() #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) if (propertiesDialogShown) { - QCUPSSupport::PagesPerSheet pagesPerSheet = propertiesDialog->widget.pageSetup->widget.pagesPerSheetCombo->currentData().value(); + QCUPSSupport::PagesPerSheet pagesPerSheet = propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo + ->currentData().value(); QCUPSSupport::PageSet pageSet = optionsPane->options.pageSetCombo->currentData().value(); @@ -918,10 +913,10 @@ void QUnixPrintWidgetPrivate::setupPrinterProperties() if (q->isOptionEnabled(QPrintDialog::PrintToFile) && (widget.printers->currentIndex() == widget.printers->count() - 1)) {// PDF - propertiesDialog->selectPdfPsPrinter(q->printer()); + propertiesDialog->selectPrinter(QPrinter::PdfFormat, QString()); } else - propertiesDialog->selectPrinter(); + propertiesDialog->selectPrinter(QPrinter::NativeFormat, widget.printers->currentText()); } void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked() -- cgit v1.2.3 From aa76fcc301ecc1faab0edff9e5f99b83eb6b3d7c Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 29 Jan 2014 15:46:01 +0100 Subject: QPrintDialog - Remove CUPS specific code We no longer use QLibrary to load CUPS, so remove checks. Switch from using QCupsSupport and QPrinterInfo to QPlatformPrintDevice. The remaining use of QCupsSupport is only for utilities to set CUPS specific options which don't need to link to CUPS directly, these will be replaced later with generic cross-platform API. Change-Id: I6e3d9e9a59633c33af0555eb28443a9fc192b27c Reviewed-by: Lars Knoll --- src/printsupport/dialogs/qprintdialog_unix.cpp | 148 ++++++++++++------------- 1 file changed, 74 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index e8f959bcd5..ab31db76aa 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -52,8 +52,11 @@ #include #include #include -#include -#include + +#include +#include + +#include #include @@ -62,12 +65,9 @@ #include "ui_qprintsettingsoutput.h" #include "ui_qprintwidget.h" -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) -# include -# include "qcupsjobwidget_p.h" -#else -# include -# include +#ifndef QT_NO_CUPS +#include +#include "qcupsjobwidget_p.h" #endif /* @@ -133,7 +133,7 @@ private: friend class QUnixPrintWidgetPrivate; Ui::QPrintPropertiesWidget widget; QDialogButtonBox *m_buttons; -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +#ifndef QT_NO_CUPS QCupsJobWidget *m_jobOptions; #endif }; @@ -180,6 +180,8 @@ public: Ui::QPrintWidget widget; QAbstractPrintDialog * q; QPrinter *printer; + QPrintDevice m_currentPrintDevice; + void updateWidget(); private: @@ -248,11 +250,9 @@ QPrintPropertiesDialog::QPrintPropertiesDialog(QAbstractPrintDialog *parent) connect(m_buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept())); connect(m_buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject())); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - if (QCUPSSupport::isAvailable()) { - m_jobOptions = new QCupsJobWidget(); - widget.tabs->addTab(m_jobOptions, tr("Job Options")); - } +#ifndef QT_NO_CUPS + m_jobOptions = new QCupsJobWidget(); + widget.tabs->addTab(m_jobOptions, tr("Job Options")); #endif } @@ -263,20 +263,16 @@ QPrintPropertiesDialog::~QPrintPropertiesDialog() void QPrintPropertiesDialog::applyPrinterProperties(QPrinter *p) { widget.pageSetup->setPrinter(p); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - if (QCUPSSupport::isAvailable()) { - m_jobOptions->setPrinter(p); - } +#ifndef QT_NO_CUPS + m_jobOptions->setPrinter(p); #endif } void QPrintPropertiesDialog::setupPrinter() const { widget.pageSetup->setupPrinter(); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - if (QCUPSSupport::isAvailable()) { - m_jobOptions->setupPrinter(); - } +#ifndef QT_NO_CUPS + m_jobOptions->setupPrinter(); #endif } @@ -323,13 +319,11 @@ void QPrintDialogPrivate::init() options.grayscale->setIconSize(QSize(32, 32)); options.grayscale->setIcon(QIcon(QLatin1String(":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"))); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +#ifndef QT_NO_CUPS // Add Page Set widget if CUPS is available - if (QCUPSSupport::isAvailable()) { - options.pageSetCombo->addItem(tr("All Pages"), QVariant::fromValue(QCUPSSupport::AllPages)); - options.pageSetCombo->addItem(tr("Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages)); - options.pageSetCombo->addItem(tr("Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages)); - } + options.pageSetCombo->addItem(tr("All Pages"), QVariant::fromValue(QCUPSSupport::AllPages)); + options.pageSetCombo->addItem(tr("Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages)); + options.pageSetCombo->addItem(tr("Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages)); #endif top->d->setOptionsPane(this); @@ -447,24 +441,27 @@ void QPrintDialogPrivate::setupPrinter() } } -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +#ifndef QT_NO_CUPS // page set - if (QCUPSSupport::isAvailable()) { - if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) { - //If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly - QCUPSSupport::PageSet pageSet = options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()).value(); - if (q->isOptionEnabled(QPrintDialog::PrintPageRange) - && p->printRange() == QPrinter::PageRange - && (q->fromPage() % 2 == 0)) { - - if (pageSet == QCUPSSupport::OddPages) - QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages); - else if (pageSet == QCUPSSupport::EvenPages) - QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages); - } else if (pageSet != QCUPSSupport::AllPages) { - QCUPSSupport::setPageSet(p, pageSet); + if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) { + //If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly + QCUPSSupport::PageSet pageSet = options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()).value(); + if (q->isOptionEnabled(QPrintDialog::PrintPageRange) + && p->printRange() == QPrinter::PageRange + && (q->fromPage() % 2 == 0)) { + + switch (pageSet) { + case QCUPSSupport::AllPages: + break; + case QCUPSSupport::OddPages: + QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages); + break; + case QCUPSSupport::EvenPages: + QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages); + break; } - + } else if (pageSet != QCUPSSupport::AllPages) { + QCUPSSupport::setPageSet(p, pageSet); } // server-side page range, since we set the page range on the printer to 0-0/AllPages above, @@ -527,26 +524,22 @@ void QPrintDialogPrivate::updateWidgets() options.printCurrentPage->setVisible(q->isOptionEnabled(QPrintDialog::PrintCurrentPage)); options.collate->setVisible(q->isOptionEnabled(QPrintDialog::PrintCollateCopies)); -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) - if (QCUPSSupport::isAvailable()) { - // Don't display Page Set if only Selection or Current Page are enabled - if (!q->isOptionEnabled(QPrintDialog::PrintPageRange) && ( - q->isOptionEnabled(QPrintDialog::PrintSelection) || - q->isOptionEnabled(QPrintDialog::PrintCurrentPage))) { - - options.pageSetCombo->setVisible(false); - options.pageSetLabel->setVisible(false); - } else { - options.pageSetCombo->setVisible(true); - options.pageSetLabel->setVisible(true); - } +#ifndef QT_NO_CUPS + // Don't display Page Set if only Selection or Current Page are enabled + if (!q->isOptionEnabled(QPrintDialog::PrintPageRange) + && (q->isOptionEnabled(QPrintDialog::PrintSelection) || q->isOptionEnabled(QPrintDialog::PrintCurrentPage))) { + options.pageSetCombo->setVisible(false); + options.pageSetLabel->setVisible(false); + } else { + options.pageSetCombo->setVisible(true); + options.pageSetLabel->setVisible(true); + } - if (!q->isOptionEnabled(QPrintDialog::PrintPageRange)) { - // If we can do CUPS server side pages selection, - // display the page range widgets - options.gbPrintRange->setVisible(true); - options.printRange->setEnabled(true); - } + if (!q->isOptionEnabled(QPrintDialog::PrintPageRange)) { + // If we can do CUPS server side pages selection, + // display the page range widgets + options.gbPrintRange->setVisible(true); + options.printRange->setEnabled(true); } #endif @@ -675,12 +668,17 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter * widget.setupUi(parent); int currentPrinterIndex = 0; - QList printers = QPrinterInfo::availablePrinters(); + QStringList printers; + QString defaultPrinter; + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) { + printers = ps->availablePrintDeviceIds(); + defaultPrinter = ps->defaultPrintDeviceId(); + } for (int i = 0; i < printers.size(); ++i) { - QPrinterInfo pInfo = printers.at(i); - widget.printers->addItem(pInfo.printerName()); - if (pInfo.isDefault()) + widget.printers->addItem(printers.at(i)); + if (printers.at(i) == defaultPrinter) currentPrinterIndex = i; } widget.properties->setEnabled(true); @@ -769,12 +767,14 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index) } if (printer) { - QString printerName = widget.printers->itemText(index); - printer->setPrinterName(printerName); + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) + m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index)); + + printer->setPrinterName(m_currentPrintDevice.id()); - QPrinterInfo printerInfo = QPrinterInfo::printerInfo(printer->printerName()); - widget.location->setText(printerInfo.location()); - widget.type->setText(printerInfo.makeAndModel()); + widget.location->setText(m_currentPrintDevice.location()); + widget.type->setText(m_currentPrintDevice.makeAndModel()); if (optionsPane) optionsPane->selectPrinter(QPrinter::NativeFormat); } @@ -841,7 +841,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties() } } } - // PDF and PS printers are not added to the dialog yet, we'll handle those cases in QUnixPrintWidgetPrivate::updateWidget + // PDF printer not added to the dialog yet, we'll handle those cases in QUnixPrintWidgetPrivate::updateWidget if (propertiesDialog) propertiesDialog->applyPrinterProperties(printer); @@ -878,7 +878,7 @@ bool QUnixPrintWidgetPrivate::checkFields() } } -#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +#ifndef QT_NO_CUPS if (propertiesDialogShown) { QCUPSSupport::PagesPerSheet pagesPerSheet = propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo ->currentData().value(); -- cgit v1.2.3 From 69e9b12001be08fe2b3f2c2def0ca3468d83b675 Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 29 Jan 2014 16:04:10 +0100 Subject: QCupsSupport - Remove obsolete CUPS code All code directly using CUPS is now in the QPA plugin and QCupsSupport is no longer needed, other than the utilities for setting CUPS options which do not need direct access to CUPS. Delete all the obsolete code. Change-Id: I561ad8af2415a9b745e2d35fd0624a5acdf27648 Reviewed-by: Lars Knoll --- src/printsupport/kernel/qcups.cpp | 481 +------------------------------------- src/printsupport/kernel/qcups_p.h | 65 ------ 2 files changed, 1 insertion(+), 545 deletions(-) (limited to 'src') diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp index e237d44dcd..a1c657eda4 100644 --- a/src/printsupport/kernel/qcups.cpp +++ b/src/printsupport/kernel/qcups.cpp @@ -41,322 +41,12 @@ #include "qcups_p.h" -#include +#include "qprintengine.h" #ifndef QT_NO_CUPS -#ifndef QT_LINUXBASE // LSB merges everything into cups.h -# include -#endif -#include - -#include - QT_BEGIN_NAMESPACE -extern double qt_multiplierForUnit(QPrinter::Unit unit, int resolution); - -typedef int (*CupsGetDests)(cups_dest_t **dests); -typedef void (*CupsFreeDests)(int num_dests, cups_dest_t *dests); -typedef const char* (*CupsGetPPD)(const char *printer); -typedef int (*CupsMarkOptions)(ppd_file_t *ppd, int num_options, cups_option_t *options); -typedef ppd_file_t* (*PPDOpenFile)(const char *filename); -typedef void (*PPDMarkDefaults)(ppd_file_t *ppd); -typedef int (*PPDMarkOption)(ppd_file_t *ppd, const char *keyword, const char *option); -typedef void (*PPDClose)(ppd_file_t *ppd); -typedef int (*PPDMarkOption)(ppd_file_t *ppd, const char *keyword, const char *option); -typedef void (*CupsFreeOptions)(int num_options, cups_option_t *options); -typedef void (*CupsSetDests)(int num_dests, cups_dest_t *dests); -typedef cups_lang_t* (*CupsLangGet)(const char *language); -typedef const char* (*CupsLangEncoding)(cups_lang_t *language); -typedef int (*CupsAddOption)(const char *name, const char *value, int num_options, cups_option_t **options); -typedef int (*CupsTempFd)(char *name, int len); -typedef int (*CupsPrintFile)(const char * name, const char * filename, const char * title, int num_options, cups_option_t * options); - -static bool cupsLoaded = false; -static int qt_cups_num_printers = 0; -static CupsGetDests _cupsGetDests = 0; -static CupsFreeDests _cupsFreeDests = 0; -static CupsGetPPD _cupsGetPPD = 0; -static PPDOpenFile _ppdOpenFile = 0; -static PPDMarkDefaults _ppdMarkDefaults = 0; -static PPDClose _ppdClose = 0; -static CupsMarkOptions _cupsMarkOptions = 0; -static PPDMarkOption _ppdMarkOption = 0; -static CupsFreeOptions _cupsFreeOptions = 0; -static CupsSetDests _cupsSetDests = 0; -static CupsLangGet _cupsLangGet = 0; -static CupsLangEncoding _cupsLangEncoding = 0; -static CupsAddOption _cupsAddOption = 0; -static CupsTempFd _cupsTempFd = 0; -static CupsPrintFile _cupsPrintFile = 0; - -static void resolveCups() -{ - QLibrary cupsLib(QLatin1String("cups"), 2); - if(cupsLib.load()) { - _cupsGetDests = (CupsGetDests) cupsLib.resolve("cupsGetDests"); - _cupsFreeDests = (CupsFreeDests) cupsLib.resolve("cupsFreeDests"); - _cupsGetPPD = (CupsGetPPD) cupsLib.resolve("cupsGetPPD"); - _cupsLangGet = (CupsLangGet) cupsLib.resolve("cupsLangGet"); - _cupsLangEncoding = (CupsLangEncoding) cupsLib.resolve("cupsLangEncoding"); - _ppdOpenFile = (PPDOpenFile) cupsLib.resolve("ppdOpenFile"); - _ppdMarkDefaults = (PPDMarkDefaults) cupsLib.resolve("ppdMarkDefaults"); - _ppdClose = (PPDClose) cupsLib.resolve("ppdClose"); - _cupsMarkOptions = (CupsMarkOptions) cupsLib.resolve("cupsMarkOptions"); - _ppdMarkOption = (PPDMarkOption) cupsLib.resolve("ppdMarkOption"); - _cupsFreeOptions = (CupsFreeOptions) cupsLib.resolve("cupsFreeOptions"); - _cupsSetDests = (CupsSetDests) cupsLib.resolve("cupsSetDests"); - _cupsAddOption = (CupsAddOption) cupsLib.resolve("cupsAddOption"); - _cupsTempFd = (CupsTempFd) cupsLib.resolve("cupsTempFd"); - _cupsPrintFile = (CupsPrintFile) cupsLib.resolve("cupsPrintFile"); - - if (_cupsGetDests && _cupsFreeDests) { - cups_dest_t *printers; - int num_printers = _cupsGetDests(&printers); - if (num_printers) - _cupsFreeDests(num_printers, printers); - qt_cups_num_printers = num_printers; - } - } - cupsLoaded = true; -} - -// ================ CUPS Support class ======================== - -QCUPSSupport::QCUPSSupport() - : - prnCount(0), - printers(0), - page_sizes(0), - currPrinterIndex(0), - currPPD(0) -{ - if (!cupsLoaded) - resolveCups(); - - // getting all available printers - if (!isAvailable()) - return; - - qt_cups_num_printers = prnCount = _cupsGetDests(&printers); - - for (int i = 0; i < prnCount; ++i) { - if (printers[i].is_default) { - currPrinterIndex = i; - break; - } - } - - if (prnCount > 0) - setCurrentPrinter(currPrinterIndex); - -#ifndef QT_NO_TEXTCODEC - cups_lang_t *cupsLang = _cupsLangGet(0); - codec = QTextCodec::codecForName(_cupsLangEncoding(cupsLang)); - if (!codec) - codec = QTextCodec::codecForLocale(); -#endif -} - -QCUPSSupport::~QCUPSSupport() -{ - if (currPPD) - _ppdClose(currPPD); - if (prnCount) - _cupsFreeDests(prnCount, printers); -} - -int QCUPSSupport::availablePrintersCount() const -{ - return prnCount; -} - -const cups_dest_t* QCUPSSupport::availablePrinters() const -{ - return printers; -} - -const ppd_file_t* QCUPSSupport::currentPPD() const -{ - return currPPD; -} - -const ppd_file_t* QCUPSSupport::setCurrentPrinter(int index) -{ - Q_ASSERT(index >= 0 && index <= prnCount); - if (index == prnCount) - return 0; - - currPrinterIndex = index; - - if (currPPD) - _ppdClose(currPPD); - currPPD = 0; - page_sizes = 0; - - const char *ppdFile = _cupsGetPPD(printers[index].name); - - if (!ppdFile) - return 0; - - currPPD = _ppdOpenFile(ppdFile); - unlink(ppdFile); - - // marking default options - _ppdMarkDefaults(currPPD); - - // marking options explicitly set - _cupsMarkOptions(currPPD, printers[currPrinterIndex].num_options, printers[currPrinterIndex].options); - - // getting pointer to page sizes - page_sizes = ppdOption("PageSize"); - - return currPPD; -} - -const ppd_file_t* QCUPSSupport::setCurrentPrinter(const QString &printerName) -{ - Q_FOREACH (const QCUPSSupport::Printer &printer, QCUPSSupport::availableUnixPrinters()) { - if (printer.name == printerName) { - return setCurrentPrinter(printer.cupsPrinterIndex); - } - } - - return 0; -} - -int QCUPSSupport::currentPrinterIndex() const -{ - return currPrinterIndex; -} - -bool QCUPSSupport::isAvailable() -{ - if(!cupsLoaded) - resolveCups(); - - return _cupsGetDests && - _cupsFreeDests && - _cupsGetPPD && - _ppdOpenFile && - _ppdMarkDefaults && - _ppdClose && - _cupsMarkOptions && - _ppdMarkOption && - _cupsFreeOptions && - _cupsSetDests && - _cupsLangGet && - _cupsLangEncoding && - _cupsAddOption && - (qt_cups_num_printers > 0); -} - -const ppd_option_t* QCUPSSupport::ppdOption(const char *key) const -{ - if (currPPD) { - for (int gr = 0; gr < currPPD->num_groups; ++gr) { - for (int opt = 0; opt < currPPD->groups[gr].num_options; ++opt) { - if (qstrcmp(currPPD->groups[gr].options[opt].keyword, key) == 0) - return &currPPD->groups[gr].options[opt]; - } - } - } - return 0; -} - -const cups_option_t* QCUPSSupport::printerOption(const QString &key) const -{ - for (int i = 0; i < printers[currPrinterIndex].num_options; ++i) { - if (QLatin1String(printers[currPrinterIndex].options[i].name) == key) - return &printers[currPrinterIndex].options[i]; - } - return 0; -} - -const ppd_option_t* QCUPSSupport::pageSizes() const -{ - return page_sizes; -} - -int QCUPSSupport::markOption(const char* name, const char* value) -{ - return _ppdMarkOption(currPPD, name, value); -} - -void QCUPSSupport::saveOptions(QList options, QList markedOptions) -{ - int oldOptionCount = printers[currPrinterIndex].num_options; - cups_option_t* oldOptions = printers[currPrinterIndex].options; - - int newOptionCount = 0; - cups_option_t* newOptions = 0; - - // copying old options that are not on the new list - for (int i = 0; i < oldOptionCount; ++i) { - bool contains = false; - for (int j = 0; j < options.count(); ++j) { - if (qstrcmp(options.at(j)->keyword, oldOptions[i].name) == 0) { - contains = true; - break; - } - } - - if (!contains) { - newOptionCount = _cupsAddOption(oldOptions[i].name, oldOptions[i].value, newOptionCount, &newOptions); - } - } - - // we can release old option list - _cupsFreeOptions(oldOptionCount, oldOptions); - - // adding marked options - for (int i = 0; i < markedOptions.count(); ++i) { - const char* name = markedOptions.at(i); - ++i; - newOptionCount = _cupsAddOption(name, markedOptions.at(i), newOptionCount, &newOptions); - } - - // placing the new option list - printers[currPrinterIndex].num_options = newOptionCount; - printers[currPrinterIndex].options = newOptions; - - // saving new default values - _cupsSetDests(prnCount, printers); -} - -QRect QCUPSSupport::paperRect(const char *choice) const -{ - if (!currPPD) - return QRect(); - for (int i = 0; i < currPPD->num_sizes; ++i) { - if (qstrcmp(currPPD->sizes[i].name, choice) == 0) - return QRect(0, 0, qRound(currPPD->sizes[i].width), qRound(currPPD->sizes[i].length)); - } - return QRect(); -} - -QRect QCUPSSupport::pageRect(const char *choice) const -{ - if (!currPPD) - return QRect(); - for (int i = 0; i < currPPD->num_sizes; ++i) { - if (qstrcmp(currPPD->sizes[i].name, choice) == 0) - return QRect(qRound(currPPD->sizes[i].left), - qRound(currPPD->sizes[i].length - currPPD->sizes[i].top), - qRound(currPPD->sizes[i].right - currPPD->sizes[i].left), - qRound(currPPD->sizes[i].top - currPPD->sizes[i].bottom)); - } - return QRect(); -} - -QStringList QCUPSSupport::options() const -{ - QStringList list; - collectMarkedOptions(list); - return list; -} - QStringList QCUPSSupport::cupsOptionsList(QPrinter *printer) { return printer->printEngine()->property(PPK_CupsOptions).toStringList(); @@ -544,175 +234,6 @@ void QCUPSSupport::setPageRange(QPrinter *printer, int pageFrom, int pageTo) setCupsOptions(printer, cupsOptions); } -bool QCUPSSupport::printerHasPPD(const char *printerName) -{ - if (!isAvailable()) - return false; - const char *ppdFile = _cupsGetPPD(printerName); - if (ppdFile) - unlink(ppdFile); - return (ppdFile != 0); -} - -QString QCUPSSupport::unicodeString(const char *s) -{ -#ifndef QT_NO_TEXTCODEC - return codec->toUnicode(s); -#else - return QLatin1String(s); -#endif -} - -void QCUPSSupport::collectMarkedOptions(QStringList& list, const ppd_group_t* group) const -{ - if (group == 0) { - if (!currPPD) - return; - for (int i = 0; i < currPPD->num_groups; ++i) { - collectMarkedOptions(list, &currPPD->groups[i]); - collectMarkedOptionsHelper(list, &currPPD->groups[i]); - } - } else { - for (int i = 0; i < group->num_subgroups; ++i) - collectMarkedOptionsHelper(list, &group->subgroups[i]); - } -} - -void QCUPSSupport::collectMarkedOptionsHelper(QStringList& list, const ppd_group_t* group) const -{ - for (int i = 0; i < group->num_options; ++i) { - for (int j = 0; j < group->options[i].num_choices; ++j) { - if (group->options[i].choices[j].marked == 1 && qstrcmp(group->options[i].choices[j].choice, group->options[i].defchoice) != 0) - list << QString::fromLocal8Bit(group->options[i].keyword) << QString::fromLocal8Bit(group->options[i].choices[j].choice); - } - } -} - -QPair QCUPSSupport::tempFd() -{ - char filename[512]; - int fd = _cupsTempFd(filename, 512); - return QPair(fd, QString::fromLocal8Bit(filename)); -} - -// Prints the given file and returns a job id. -int QCUPSSupport::printFile(const char * printerName, const char * filename, const char * title, - int num_options, cups_option_t * options) -{ - return _cupsPrintFile(printerName, filename, title, num_options, options); -} - -QCUPSSupport::Printer::Printer(const QString &n) : name(n), isDefault(false), cupsPrinterIndex(-1) -{ -} - -QList QCUPSSupport::availableUnixPrinters() -{ - QList printers; - - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - int cupsPrinterCount = cups.availablePrintersCount(); - const cups_dest_t* cupsPrinters = cups.availablePrinters(); - for (int i = 0; i < cupsPrinterCount; ++i) { - QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name)); - if (cupsPrinters[i].instance) - printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance); - - Printer p(printerName); - if (cupsPrinters[i].is_default) - p.isDefault = true; - p.cupsPrinterIndex = i; - printers.append(p); - } - } - - return printers; -} - -// preserve names in ascending order for the binary search -static const struct NamedPaperSize { - const char *const name; - QPrinter::PaperSize size; -} named_sizes_map[QPrinter::NPageSize] = { - { "A0", QPrinter::A0 }, - { "A1", QPrinter::A1 }, - { "A2", QPrinter::A2 }, - { "A3", QPrinter::A3 }, - { "A4", QPrinter::A4 }, - { "A5", QPrinter::A5 }, - { "A6", QPrinter::A6 }, - { "A7", QPrinter::A7 }, - { "A8", QPrinter::A8 }, - { "A9", QPrinter::A9 }, - { "B0", QPrinter::B0 }, - { "B1", QPrinter::B1 }, - { "B10", QPrinter::B10 }, - { "B2", QPrinter::B2 }, - { "B4", QPrinter::B4 }, - { "B5", QPrinter::B5 }, - { "B6", QPrinter::B6 }, - { "B7", QPrinter::B7 }, - { "B8", QPrinter::B8 }, - { "B9", QPrinter::B9 }, - { "C5E", QPrinter::C5E }, - { "Comm10E", QPrinter::Comm10E }, - { "Custom", QPrinter::Custom }, - { "DLE", QPrinter::DLE }, - { "Executive", QPrinter::Executive }, - { "Folio", QPrinter::Folio }, - { "Ledger", QPrinter::Ledger }, - { "Legal", QPrinter::Legal }, - { "Letter", QPrinter::Letter }, - { "Tabloid", QPrinter::Tabloid } -}; - -inline bool operator<(const char *name, const NamedPaperSize &data) -{ return qstrcmp(name, data.name) < 0; } -inline bool operator<(const NamedPaperSize &data, const char *name) -{ return qstrcmp(data.name, name) < 0; } - -static inline QPrinter::PaperSize string2PaperSize(const char *name) -{ - const NamedPaperSize *r = std::lower_bound(named_sizes_map, named_sizes_map + QPrinter::NPageSize, name); - if ((r != named_sizes_map + QPrinter::NPageSize) && !(name < *r)) - return r->size; - return QPrinter::Custom; -} - -QList QCUPSSupport::getCupsPrinterPaperSizes(int cupsPrinterIndex) -{ - QList result; - if (!QCUPSSupport::isAvailable() || cupsPrinterIndex < 0) - return result; - // Find paper sizes from CUPS. - QCUPSSupport cups; - cups.setCurrentPrinter(cupsPrinterIndex); - if (const ppd_option_t* size = cups.pageSizes()) { - for (int j = 0; j < size->num_choices; ++j) - result.append(string2PaperSize(size->choices[j].choice)); - } - return result; -} - -QList > QCUPSSupport::getCupsPrinterPaperSizesWithNames(int cupsPrinterIndex) -{ - QList > result; - if (!QCUPSSupport::isAvailable() || cupsPrinterIndex < 0) - return result; - // Find paper sizes from CUPS. - QCUPSSupport cups; - cups.setCurrentPrinter(cupsPrinterIndex); - if (const ppd_option_t* size = cups.pageSizes()) { - for (int j = 0; j < size->num_choices; ++j) { - double multiplier = qt_multiplierForUnit(QPrinter::Millimeter, 0); // resolution is not needed here - QSize sz = cups.paperRect(size->choices[j].choice).size(); - result.append(qMakePair(QString::fromUtf8(size->choices[j].text), QSizeF(sz.width() / multiplier, sz.height() / multiplier))); - } - } - return result; -} - QT_END_NAMESPACE #endif // QT_NO_CUPS diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h index 337f2250c5..0b327d4228 100644 --- a/src/printsupport/kernel/qcups_p.h +++ b/src/printsupport/kernel/qcups_p.h @@ -54,15 +54,10 @@ // #include "QtCore/qstring.h" #include "QtCore/qstringlist.h" -#include "QtCore/qpair.h" #include "QtPrintSupport/qprinter.h" #include "QtCore/qdatetime.h" #ifndef QT_NO_CUPS -#include -#include -#include -#include "qprintengine.h" QT_BEGIN_NAMESPACE @@ -72,22 +67,9 @@ QT_BEGIN_NAMESPACE // removed from the dialogs. #define PPK_CupsOptions QPrintEngine::PrintEnginePropertyKey(0xfe00) -Q_DECLARE_TYPEINFO(cups_option_t, Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE); - class Q_PRINTSUPPORT_EXPORT QCUPSSupport { public: - struct Printer - { - Printer(const QString &name = QString()); - - QString name; - bool isDefault; - int cupsPrinterIndex; - }; - QCUPSSupport(); - ~QCUPSSupport(); - // Enum for values of job-hold-until option enum JobHoldUntil { NoHold = 0, //CUPS Default @@ -140,28 +122,6 @@ public: TopToBottomRightToLeft }; - static bool isAvailable(); - static int cupsVersion() { return isAvailable() ? CUPS_VERSION_MAJOR*10000+CUPS_VERSION_MINOR*100+CUPS_VERSION_PATCH : 0; } - int availablePrintersCount() const; - const cups_dest_t* availablePrinters() const; - int currentPrinterIndex() const; - const ppd_file_t* setCurrentPrinter(int index); - const ppd_file_t* setCurrentPrinter(const QString &printerName); - - const ppd_file_t* currentPPD() const; - const ppd_option_t* ppdOption(const char *key) const; - - const cups_option_t* printerOption(const QString &key) const; - const ppd_option_t* pageSizes() const; - - int markOption(const char* name, const char* value); - void saveOptions(QList options, QList markedOptions); - - QRect paperRect(const char *choice) const; - QRect pageRect(const char *choice) const; - - QStringList options() const; - static QStringList cupsOptionsList(QPrinter *printer); static void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions); static void setCupsOption(QStringList &cupsOptions, const QString &option, const QString &value); @@ -174,31 +134,6 @@ public: static void setPagesPerSheetLayout(QPrinter *printer, const PagesPerSheet pagesPerSheet, const PagesPerSheetLayout pagesPerSheetLayout); static void setPageRange(QPrinter *printer, int pageFrom, int pageTo); - - static bool printerHasPPD(const char *printerName); - - QString unicodeString(const char *s); - - QPair tempFd(); - int printFile(const char * printerName, const char * filename, const char * title, - int num_options, cups_option_t * options); - - static QList availableUnixPrinters(); - static QList getCupsPrinterPaperSizes(int cupsPrinterIndex); - static QList > getCupsPrinterPaperSizesWithNames(int cupsPrinterIndex); - -private: - void collectMarkedOptions(QStringList& list, const ppd_group_t* group = 0) const; - void collectMarkedOptionsHelper(QStringList& list, const ppd_group_t* group) const; - - int prnCount; - cups_dest_t *printers; - const ppd_option_t* page_sizes; - int currPrinterIndex; - ppd_file_t *currPPD; -#ifndef QT_NO_TEXTCODEC - QTextCodec *codec; -#endif }; QT_END_NAMESPACE -- cgit v1.2.3 From 833a43d56c644b2201643b1e7593b0ee86d0d258 Mon Sep 17 00:00:00 2001 From: John Layt Date: Thu, 13 Mar 2014 20:24:16 +0100 Subject: QtPrintSupport - Fix QT_NO_PRINTER build Fix the QT_NO_PRINTER build for issues that have accumulated over last few months, and in the new changes already approved. Change-Id: I9aed21dee861837fd1a68a96692c873a4f5be293 Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qcocoaprintdevice.h | 5 ++--- src/plugins/platforms/cocoa/qcocoaprintdevice.mm | 4 ++++ src/plugins/printsupport/cups/qcupsprintersupport_p.h | 5 ++--- src/plugins/printsupport/cups/qppdprintdevice.cpp | 4 ++++ src/plugins/printsupport/cups/qppdprintdevice.h | 5 ++--- src/plugins/printsupport/windows/qwindowsprintdevice.cpp | 4 ++++ src/plugins/printsupport/windows/qwindowsprintdevice.h | 5 ++--- src/printsupport/dialogs/qprintdialog_mac.mm | 4 ++-- src/printsupport/kernel/qplatformprintdevice.cpp | 4 ++++ src/printsupport/kernel/qplatformprintdevice.h | 6 ++++-- src/printsupport/kernel/qprintdevice.cpp | 4 ++++ src/printsupport/kernel/qprintdevice_p.h | 4 ++++ src/printsupport/widgets/qcupsjobwidget.cpp | 4 ++++ src/printsupport/widgets/qcupsjobwidget_p.h | 4 ++++ 14 files changed, 46 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h index 3f1fa475d5..30a2155bc7 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h @@ -53,11 +53,10 @@ // We mean it. // -#include // Some feature dependencies might define QT_NO_PRINTER -#ifndef QT_NO_PRINTER - #include +#ifndef QT_NO_PRINTER + #include "qt_mac_p.h" #include diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index d8b01ec07f..3061e84470 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode) { if (mode == kPMDuplexTumble) @@ -495,4 +497,6 @@ PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const return paper; } +#endif // QT_NO_PRINTER + QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h index 27741a52fe..1cba4e997b 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h +++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h @@ -43,11 +43,10 @@ #ifndef QCUPSPRINTERSUPPORT_H #define QCUPSPRINTERSUPPORT_H -#include // Some feature dependencies might define QT_NO_PRINTER -#ifndef QT_NO_PRINTER - #include +#ifndef QT_NO_PRINTER + #include QT_BEGIN_NAMESPACE diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp index fb2d34ed26..56ae5600c4 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.cpp +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + QPpdPrintDevice::QPpdPrintDevice() : QPlatformPrintDevice(), m_cupsDest(0), @@ -496,4 +498,6 @@ cups_ptype_e QPpdPrintDevice::printerTypeFlags() const return static_cast(printerOption("printer-type").toUInt()); } +#endif // QT_NO_PRINTER + QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h index cdea40dd6d..982f46d71f 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.h +++ b/src/plugins/printsupport/cups/qppdprintdevice.h @@ -53,11 +53,10 @@ // We mean it. // -#include // Some feature dependencies might define QT_NO_PRINTER -#ifndef QT_NO_PRINTER - #include +#ifndef QT_NO_PRINTER + #include #include diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index c45e266aaa..fce4bbb42b 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -45,6 +45,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + extern qreal qt_pointMultiplier(QPageLayout::Unit unit); static inline uint qwcsnlen(const wchar_t *str, uint maxlen) @@ -469,4 +471,6 @@ QString QWindowsPrintDevice::defaultPrintDeviceId() return QString::fromWCharArray(name.data()); } +#endif // QT_NO_PRINTER + QT_END_NAMESPACE diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h index f619876dcb..2d11787305 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.h +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h @@ -53,11 +53,10 @@ // We mean it. // -#include // Some feature dependencies might define QT_NO_PRINTER -#ifndef QT_NO_PRINTER - #include +#ifndef QT_NO_PRINTER + #include QT_BEGIN_NAMESPACE diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index 7194aee22f..9ff7c4766a 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -53,10 +53,10 @@ #ifndef QT_NO_PRINTDIALOG -extern qreal qt_pointMultiplier(QPageLayout::Unit unit); - QT_BEGIN_NAMESPACE +extern qreal qt_pointMultiplier(QPageLayout::Unit unit); + class QPrintDialogPrivate : public QAbstractPrintDialogPrivate { Q_DECLARE_PUBLIC(QPrintDialog) diff --git a/src/printsupport/kernel/qplatformprintdevice.cpp b/src/printsupport/kernel/qplatformprintdevice.cpp index df0ef3111b..4932bf1d04 100644 --- a/src/printsupport/kernel/qplatformprintdevice.cpp +++ b/src/printsupport/kernel/qplatformprintdevice.cpp @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + QPlatformPrintDevice::QPlatformPrintDevice() : m_isRemote(false), m_supportsMultipleCopies(false), @@ -386,4 +388,6 @@ QPageSize QPlatformPrintDevice::createPageSize(int windowsId, const QSize &size, return QPageSize(windowsId, size, localizedName); } +#endif // QT_NO_PRINTER + QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qplatformprintdevice.h b/src/printsupport/kernel/qplatformprintdevice.h index 04d614085f..7674c50c2f 100644 --- a/src/printsupport/kernel/qplatformprintdevice.h +++ b/src/printsupport/kernel/qplatformprintdevice.h @@ -53,8 +53,6 @@ // We mean it. // -#include "qplatformprintdevice.h" - #include #include @@ -63,6 +61,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + class Q_PRINTSUPPORT_EXPORT QPlatformPrintDevice : public QSharedData { public: @@ -177,4 +177,6 @@ protected: QT_END_NAMESPACE +#endif // QT_NO_PRINTER + #endif // QPLATFORMPRINTDEVICE_H diff --git a/src/printsupport/kernel/qprintdevice.cpp b/src/printsupport/kernel/qprintdevice.cpp index c4ba12e0b0..eb0af455ee 100644 --- a/src/printsupport/kernel/qprintdevice.cpp +++ b/src/printsupport/kernel/qprintdevice.cpp @@ -44,6 +44,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + QPrintDevice::QPrintDevice() : d(new QPlatformPrintDevice()) { @@ -248,4 +250,6 @@ QList QPrintDevice::supportedMimeTypes() const return isValid() ? d->supportedMimeTypes() : QList(); } +#endif // QT_NO_PRINTER + QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h index 55124c16d4..4d63d46aeb 100644 --- a/src/printsupport/kernel/qprintdevice_p.h +++ b/src/printsupport/kernel/qprintdevice_p.h @@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + class QPlatformPrintDevice; class QMarginsF; class QMimeType; @@ -142,4 +144,6 @@ Q_DECLARE_SHARED(QPrintDevice) QT_END_NAMESPACE +#endif // QT_NO_PRINTER + #endif // QPLATFORMPRINTDEVICE_H diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp index 9940e6a1af..7fd3e0105d 100644 --- a/src/printsupport/widgets/qcupsjobwidget.cpp +++ b/src/printsupport/widgets/qcupsjobwidget.cpp @@ -56,6 +56,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + /*! \internal \class QCupsJobWidget @@ -212,4 +214,6 @@ QCUPSSupport::BannerPage QCupsJobWidget::endBannerPage() const return m_ui.endBannerPageCombo->itemData(m_ui.endBannerPageCombo->currentIndex()).value(); } +#endif // QT_NO_PRINTER + QT_END_NAMESPACE diff --git a/src/printsupport/widgets/qcupsjobwidget_p.h b/src/printsupport/widgets/qcupsjobwidget_p.h index a5e2bf8083..2a50a12b89 100644 --- a/src/printsupport/widgets/qcupsjobwidget_p.h +++ b/src/printsupport/widgets/qcupsjobwidget_p.h @@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + class QString; class QTime; class QPrinter; @@ -106,6 +108,8 @@ private: Q_DISABLE_COPY(QCupsJobWidget) }; +#endif // QT_NO_PRINTER + QT_END_NAMESPACE #endif // QCUPSJOBWIDGET_P_H -- cgit v1.2.3 From 3d05fa25f2563b5f7d94fd7988f17923e2e3165d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Mar 2014 14:28:16 +0100 Subject: Remove unused static const variable clang on Mac OS complains about it. Change-Id: I7a385eb520c5098cf61a0d8c2e1de0731db2e1ae Reviewed-by: Kai Koehne --- src/widgets/widgets/qmenu.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 2820608621..6ad9c4073c 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -433,10 +433,6 @@ QRect QMenuPrivate::actionRect(QAction *act) const return actionRects.at(index); } -#if defined(Q_OS_MAC) -static const qreal MenuFadeTimeInSec = 0.150; -#endif - void QMenuPrivate::hideUpToMenuBar() { Q_Q(QMenu); -- cgit v1.2.3 From a4080e47194754d717718b00f63c5f7326bf269d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 13 Feb 2014 17:20:09 +0100 Subject: Recognize RGBA8888 formats when converting to CGImage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qt_mac_image_to_cgimage incorrectly assumes any 32bit QImage format is one ARGB32 form. This is no longer correct with the introduction of RGBA8888 format. This patch recognizes the formats a maps them to the native support for them in CGImage. It also removes a duplicate method. The codepath appears to be only used by the old coregraphics paintengine and MIME handling. Which means RGBA images are probably printed and copy/pasted incorrectly at the moment. Task-number: QTBUG-36818 Change-Id: Ie6292defdbaef3e6105cf993e12911eded0918dc Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoahelpers.mm | 22 ++++++++++---- src/plugins/platforms/cocoa/qpaintengine_mac.mm | 40 +------------------------ 2 files changed, 17 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 8975605e5c..a73944c07c 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -102,21 +102,31 @@ CGImageRef qt_mac_toCGImage(const QImage &inImage) uint cgflags = kCGImageAlphaNone; switch (image.format()) { case QImage::Format_ARGB32_Premultiplied: - cgflags = kCGImageAlphaPremultipliedFirst; + cgflags = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; break; case QImage::Format_ARGB32: - cgflags = kCGImageAlphaFirst; + cgflags = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; break; case QImage::Format_RGB32: - cgflags = kCGImageAlphaNoneSkipFirst; + cgflags = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; break; case QImage::Format_RGB888: - cgflags |= kCGImageAlphaNone; - break; + cgflags = kCGImageAlphaNone | kCGBitmapByteOrder32Big; + break; + case QImage::Format_RGBA8888_Premultiplied: + cgflags = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; + break; + case QImage::Format_RGBA8888: + cgflags = kCGImageAlphaLast | kCGBitmapByteOrder32Big; + break; + case QImage::Format_RGBX8888: + cgflags = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big; + break; default: + Q_ASSERT(false); // Should never be reached. break; } - cgflags |= kCGBitmapByteOrder32Host; + QCFType dataProvider = qt_mac_CGDataProvider(image); return CGImageCreate(image.width(), image.height(), 8, 32, image.bytesPerLine(), diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 61fbe3a61f..ef67d1166f 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -979,43 +979,6 @@ static void drawImageReleaseData (void *info, const void *, size_t) delete static_cast(info); } -CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0) -{ - QImage *image; - if (img.depth() != 32) - image = new QImage(img.convertToFormat(QImage::Format_ARGB32_Premultiplied)); - else - image = new QImage(img); - - uint cgflags = kCGImageAlphaNone; - switch (image->format()) { - case QImage::Format_ARGB32_Premultiplied: - cgflags = kCGImageAlphaPremultipliedFirst; - break; - case QImage::Format_ARGB32: - cgflags = kCGImageAlphaFirst; - break; - case QImage::Format_RGB32: - cgflags = kCGImageAlphaNoneSkipFirst; - default: - break; - } -#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - QCFType dataProvider = CGDataProviderCreateWithData(image, - static_cast(image)->bits(), - image->byteCount(), - drawImageReleaseData); - if (imagePtr) - *imagePtr = image; - return CGImageCreate(image->width(), image->height(), 8, 32, - image->bytesPerLine(), - QCoreGraphicsPaintEngine::macGenericColorSpace(), - cgflags, dataProvider, 0, false, kCGRenderingIntentDefault); - -} - void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr, Qt::ImageConversionFlags flags) { @@ -1026,8 +989,7 @@ void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, con if (img.isNull() || state->compositionMode() == QPainter::CompositionMode_Destination) return; - const QImage *image; - QCFType cgimage = qt_mac_createCGImageFromQImage(img, &image); + QCFType cgimage = qt_mac_toCGImage(img); CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); if (QRectF(0, 0, img.width(), img.height()) != sr) cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), -- cgit v1.2.3 From fc3a1fba45fed48df228134c9996988bf32c7c62 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 17 Mar 2014 14:09:31 +0100 Subject: Windows: Allow for custom input context plugins. Task-number: QTBUG-37556 Change-Id: I9719138e1b09026f0971f8d3eeae525fc8951c0d Reviewed-by: Joerg Bornemann Reviewed-by: Jonathan Liu --- src/plugins/platforms/windows/qwindowsintegration.cpp | 13 +++++++++++-- src/plugins/platforms/windows/qwindowsintegration.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index e0e8753e14..de34663286 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -83,6 +83,7 @@ # include "qwindowssessionmanager.h" #endif #include +#include #include #include @@ -158,7 +159,7 @@ struct QWindowsIntegrationPrivate #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) QOpenGLStaticContextPtr m_staticOpenGLContext; #endif - QWindowsInputContext m_inputContext; + QScopedPointer m_inputContext; #ifndef QT_NO_ACCESSIBILITY QWindowsAccessibility m_accessibility; #endif @@ -224,6 +225,14 @@ QWindowsIntegration::~QWindowsIntegration() { } +void QWindowsIntegration::initialize() +{ + if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create()) + d->m_inputContext.reset(pluginContext); + else + d->m_inputContext.reset(new QWindowsInputContext); +} + bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { @@ -441,7 +450,7 @@ QPlatformDrag *QWindowsIntegration::drag() const QPlatformInputContext * QWindowsIntegration::inputContext() const { - return &d->m_inputContext; + return d->m_inputContext.data(); } #ifndef QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 2202ebd39e..0f417c8239 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -76,6 +76,7 @@ public: virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; #endif virtual QAbstractEventDispatcher *createEventDispatcher() const; + void initialize() Q_DECL_OVERRIDE; #ifndef QT_NO_CLIPBOARD virtual QPlatformClipboard *clipboard() const; # ifndef QT_NO_DRAGANDDROP -- cgit v1.2.3 From a1a2a038db4c67add9350edf900583323c9cff5b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 12 Mar 2014 11:20:37 +0100 Subject: Warn if the time taken by QTest::qSleep() is more than 50% off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like this we can find out more easily if autotests fail because of flaky timing. Change-Id: I57b10f5fc4908bed7d00990641b2ddfd4ea84a11 Reviewed-by: Jan Arve Sæther Reviewed-by: Thiago Macieira --- src/testlib/qtestcase.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 10bf200f4f..7b225ef5b4 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2863,6 +2863,8 @@ bool QTest::currentTestFailed() void QTest::qSleep(int ms) { QTEST_ASSERT(ms > 0); + QElapsedTimer timer; + timer.start(); #if defined(Q_OS_WINRT) WaitForSingleObjectEx(GetCurrentThread(), ms, true); @@ -2872,6 +2874,15 @@ void QTest::qSleep(int ms) struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); #endif + // Warn if the elapsed time was more than 50% longer or more than 10% shorter than the + // requested time. + qint64 requested = 1000000 * (qint64)ms; + qint64 diff = timer.nsecsElapsed() - requested; + if (diff * 2 > requested || diff * 10 < -requested) { + QTestLog::warn(qPrintable( + QString::fromLatin1("QTest::qSleep() should have taken %1ns, but actually took %2ns!") + .arg(requested).arg(diff + requested)), __FILE__, __LINE__); + } } /*! \internal -- cgit v1.2.3 From f6d3b65e455272d259f98cb900f46c8de765e174 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 11 Mar 2014 15:56:26 +0100 Subject: QFileDialog: documentation clarifications about file type filtering *.* is not a portable file type filter. Anyway it's better to filter by mime types, because it's more inclusive now and may even get better in the future. Task-number: QTBUG-37393 Change-Id: Ide3c3dfc47cd4b4c55d842b73de5369a0596a546 Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfiledialog.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index bb73ef5cda..80e8d152ff 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1313,13 +1313,13 @@ QStringList qt_make_filter_list(const QString &filter) Sets the filter used in the file dialog to the given \a filter. If \a filter contains a pair of parentheses containing one or more - of \b{anything*something}, separated by spaces, then only the + filename-wildcard patterns, separated by spaces, then only the text contained in the parentheses is used as the filter. This means that these calls are all equivalent: \snippet code/src_gui_dialogs_qfiledialog.cpp 6 - \sa setNameFilters() + \sa setMimeTypeFilters(), setNameFilters() */ void QFileDialog::setNameFilter(const QString &filter) { @@ -1373,7 +1373,19 @@ QStringList qt_strip_filters(const QStringList &filters) Sets the \a filters used in the file dialog. + Note that the filter \b{*.*} is not portable, because the historical + assumption that the file extension determines the file type is not + consistent on every operating system. It is possible to have a file with no + dot in its name (for example, \c Makefile). In a native Windows file + dialog, \b{*.*} will match such files, while in other types of file dialogs + it may not. So it is better to use \b{*} if you mean to select any file. + \snippet code/src_gui_dialogs_qfiledialog.cpp 7 + + \l setMimeTypeFilters() has the advantage of providing all possible name + filters for each file type. For example, JPEG images have three possible + extensions; if your application can open such files, selecting the + \c image/jpeg mime type as a filter will allow you to open all of them. */ void QFileDialog::setNameFilters(const QStringList &filters) { -- cgit v1.2.3 From 0a803dc90a1ce31009a4bea3f43a2f200cb3a22e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Mar 2014 14:49:29 +0100 Subject: Add note to docs about normalization in setAttributeBuffer Task-number: QTBUG-37103 Change-Id: I0b1716b76e10c65871c6a96dab5d8d81c95095d7 Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopenglshaderprogram.cpp | 6 ++++++ src/opengl/qglshaderprogram.cpp | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index d2429cdd23..bfde270446 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -1516,6 +1516,9 @@ void QOpenGLShaderProgram::setAttributeArray The setAttributeBuffer() function can be used to set the attribute array to an offset within a vertex buffer. + \note Normalization will be enabled. If this is not desired, call + glVertexAttribPointer directly through QOpenGLFunctions. + \sa setAttributeValue(), setUniformValue(), enableAttributeArray() \sa disableAttributeArray(), setAttributeBuffer() */ @@ -1659,6 +1662,9 @@ void QOpenGLShaderProgram::setAttributeArray on the \a location. Otherwise the value specified with setAttributeValue() for \a location will be used. + \note Normalization will be enabled. If this is not desired, call + glVertexAttribPointer directly through QOpenGLFunctions. + \sa setAttributeArray() */ void QOpenGLShaderProgram::setAttributeBuffer diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 7261b68a88..65f217edf2 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -1553,6 +1553,9 @@ void QGLShaderProgram::setAttributeArray The setAttributeBuffer() function can be used to set the attribute array to an offset within a vertex buffer. + \note Normalization will be enabled. If this is not desired, call + glVertexAttribPointer directly through QGLFunctions. + \sa setAttributeValue(), setUniformValue(), enableAttributeArray() \sa disableAttributeArray(), setAttributeBuffer() \since 4.7 @@ -1698,6 +1701,9 @@ void QGLShaderProgram::setAttributeArray on the \a location. Otherwise the value specified with setAttributeValue() for \a location will be used. + \note Normalization will be enabled. If this is not desired, call + glVertexAttribPointer directly though QGLFunctions. + \sa setAttributeArray() \since 4.7 */ -- cgit v1.2.3 From 946c0925548adca627ef6c41b8e73e46cc48dbce Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 15 Mar 2014 01:11:14 +0200 Subject: QGraphicsSimpleTextItem: Fix drawing the outline with pen, when set QTextLayout's setAdditionalFormats() is expected to invalidate the shaping results, so that the layouting must be done *after* the format range(s) gets applied. Task-number: QTBUG-33475 Change-Id: I6b948fc179da915545a98ac36f2c20163947ec9e Reviewed-by: Andy Shaw Reviewed-by: Lars Knoll --- src/widgets/graphicsview/qgraphicsitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index f1b3d95f9c..d4edc63403 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -10778,7 +10778,6 @@ void QGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphic tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); QStackTextEngine engine(tmp, d->font); QTextLayout layout(&engine); - setupTextLayout(&layout); QPen p; p.setBrush(d->brush); @@ -10795,6 +10794,7 @@ void QGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphic layout.setAdditionalFormats(formats); } + setupTextLayout(&layout); layout.draw(painter, QPointF(0, 0)); if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus)) -- cgit v1.2.3 From 4f2872c64fc1e3a5a0fd58a94c521f4b128f4a5c Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 15 Mar 2014 01:20:36 +0200 Subject: Make QTextEngine::setAdditionalFormats() invalidate cached results ...which ensures we're not getting the formatting/rendering artefacts in case of QStackTextEngine. Change-Id: Ia0696a3e67eb866cf9776c6649c43775944edd1d Reviewed-by: Andy Shaw Reviewed-by: Lars Knoll --- src/gui/text/qtextengine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 0298adde7a..3b079b7ee3 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2374,6 +2374,7 @@ void QTextEngine::freeMemory() layoutData->hasBidi = false; layoutData->layoutState = LayoutEmpty; layoutData->haveCharAttributes = false; + layoutData->items.clear(); } for (int i = 0; i < lines.size(); ++i) { lines[i].justified = 0; @@ -2520,7 +2521,8 @@ void QTextEngine::setAdditionalFormats(const QList &fo specialData->addFormats = formatList; indexAdditionalFormats(); } - resetFontEngineCache(); + invalidate(); + clearLineData(); } void QTextEngine::indexAdditionalFormats() -- cgit v1.2.3 From 9b58f95c63dbd45b31cf9b5a82582807fd5aecd2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Mar 2014 18:42:47 +0100 Subject: Doc: Add docs for QtConcurrent::{Unhandled,Exception} Change-Id: I2a9f28e572f8e59e260f659b6d17721037cbd38e Reviewed-by: Sze Howe Koh Reviewed-by: Thiago Macieira --- src/concurrent/doc/src/qtconcurrent-module.qdoc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/concurrent/doc/src/qtconcurrent-module.qdoc b/src/concurrent/doc/src/qtconcurrent-module.qdoc index 37298017c7..d9cc953a05 100644 --- a/src/concurrent/doc/src/qtconcurrent-module.qdoc +++ b/src/concurrent/doc/src/qtconcurrent-module.qdoc @@ -36,3 +36,17 @@ The Qt Concurrent module extends the basic threading support found in \l{Qt Core} module and simplifies the development of code that can be executed in parallel on all available CPU cores. */ + +/*! + \typedef QtConcurrent::Exception + \obsolete + + Use QException from \l{Qt Core} instead. +*/ + +/*! + \typedef QtConcurrent::UnhandledException + \obsolete + + Use QUnhandledException from \l{Qt Core} instead. +*/ -- cgit v1.2.3 From b4a427bac6f16d4e81e6a9cdb7c78bc8ae7f42b4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 28 Feb 2014 21:30:12 +0100 Subject: Doc: document QSharedPointer::swap() method The function is already present for quite some time, but was never documented, so declare it as \since 5.3. Add swap() function to qsharedpointer.h so it's visible to QDoc, too. Change-Id: I8eba420878a096392fd181a180d5751101d37a50 Reviewed-by: Thiago Macieira --- src/corelib/tools/qsharedpointer.cpp | 8 ++++++++ src/corelib/tools/qsharedpointer.h | 2 ++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 77409f5c71..a610fc46e5 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -477,6 +477,14 @@ you will get a compiler error. */ +/*! + \fn void QSharedPointer::swap(QSharedPointer &other); + \since 5.3 + + Swaps this shared pointer instance with \a other. This function is + very fast and never fails. +*/ + /*! \fn T *QSharedPointer::data() const diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index 7d1f00814d..34b4bfbb12 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -79,6 +79,8 @@ public: QSharedPointer &operator=(const QSharedPointer &other); QSharedPointer &operator=(const QWeakPointer &other); + void swap(QSharedPointer &other); + QWeakPointer toWeakRef() const; void clear(); -- cgit v1.2.3 From 513a49d62c34e6b0454bbcbe8a94831d019651a8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 17 Mar 2014 17:27:21 +0100 Subject: Fix translation of QtPrintSupport and QPageSize. Add translator comments, fix spelling, reduce repetitive messages. Change-Id: Id4cbbc3de8fa261cf8f125c5faf735dc608e2b15 Reviewed-by: Robert Loehning Reviewed-by: Andy Shaw Reviewed-by: John Layt --- src/gui/painting/qpagesize.cpp | 26 +++++++++++++--------- src/printsupport/dialogs/qpagesetupdialog_unix.cpp | 6 +++++ 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpagesize.cpp b/src/gui/painting/qpagesize.cpp index 6a0e61e8a1..6698d77bbd 100644 --- a/src/gui/painting/qpagesize.cpp +++ b/src/gui/painting/qpagesize.cpp @@ -1484,6 +1484,12 @@ QString QPageSize::key(QPageSize::PageSizeId pageSizeId) return QString::fromUtf8(qt_pageSizes[pageSizeId].mediaOption); } +static QString msgImperialPageSizeInch(int width, int height) +{ + //: Page size in 'Inch'. + return QCoreApplication::translate("QPageSize", "%1 x %2 in").arg(width).arg(height); +} + /*! Returns the localized name of the standard \a pageSizeId. @@ -1605,7 +1611,7 @@ QString QPageSize::name(QPageSize::PageSizeId pageSizeId) case QPageSize::LetterSmall: return QCoreApplication::translate("QPageSize", "Letter Small"); case QPageSize::TabloidExtra: - return QCoreApplication::translate("QPageSize", "Tabliod Extra"); + return QCoreApplication::translate("QPageSize", "Tabloid Extra"); case QPageSize::ArchA: return QCoreApplication::translate("QPageSize", "Architect A"); case QPageSize::ArchB: @@ -1617,23 +1623,23 @@ QString QPageSize::name(QPageSize::PageSizeId pageSizeId) case QPageSize::ArchE: return QCoreApplication::translate("QPageSize", "Architect E"); case QPageSize::Imperial7x9: - return QCoreApplication::translate("QPageSize", "7 x 9 in"); + return msgImperialPageSizeInch(7, 9); case QPageSize::Imperial8x10: - return QCoreApplication::translate("QPageSize", "8 x 10 in"); + return msgImperialPageSizeInch(8, 10); case QPageSize::Imperial9x11: - return QCoreApplication::translate("QPageSize", "9 x 11 in"); + return msgImperialPageSizeInch(9, 11); case QPageSize::Imperial9x12: - return QCoreApplication::translate("QPageSize", "9 x 12 in"); + return msgImperialPageSizeInch(9, 12); case QPageSize::Imperial10x11: - return QCoreApplication::translate("QPageSize", "10 x 11 in"); + return msgImperialPageSizeInch(10, 11); case QPageSize::Imperial10x13: - return QCoreApplication::translate("QPageSize", "10 x 13 in"); + return msgImperialPageSizeInch(10, 13); case QPageSize::Imperial10x14: - return QCoreApplication::translate("QPageSize", "10 x 14 in"); + return msgImperialPageSizeInch(10, 14); case QPageSize::Imperial12x11: - return QCoreApplication::translate("QPageSize", "12 x 11 in"); + return msgImperialPageSizeInch(12, 11); case QPageSize::Imperial15x11: - return QCoreApplication::translate("QPageSize", "15 x 11 in"); + return msgImperialPageSizeInch(15, 11); case QPageSize::Note: return QCoreApplication::translate("QPageSize", "Note"); case QPageSize::Quarto: diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp index 118d0c22c6..b9041bb242 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp @@ -412,21 +412,27 @@ void QPageSetupWidget::updateWidget() QString suffix; switch (m_units) { case QPageLayout::Millimeter: + //: Unit 'Millimeter' suffix = tr("mm"); break; case QPageLayout::Point: + //: Unit 'Points' suffix = tr("pt"); break; case QPageLayout::Inch: + //: Unit 'Inch' suffix = tr("in"); break; case QPageLayout::Pica: + //: Unit 'Pica' suffix = tr("P̸"); break; case QPageLayout::Didot: + //: Unit 'Didot' suffix = tr("DD"); break; case QPageLayout::Cicero: + //: Unit 'Cicero' suffix = tr("CC"); break; } -- cgit v1.2.3 From fd6728a5bc41059e660c697cffcf1140751a12e2 Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 12 Mar 2014 20:29:56 +0100 Subject: QPrinter - Doc fix Remove duplicated documentation. Change-Id: I53b6430b69b0e76a04cdc12b32a6bd59756acaa8 Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprinter.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'src') diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 65dcf515b7..153fb23d36 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -365,7 +365,7 @@ void QPrinterPrivate::setProperty(QPrintEngine::PrintEnginePropertyKey key, cons \value PageRange The specified page range should be printed. \value CurrentPage Only the current page should be printed. - \sa QAbstractPrintDialog::PrintRange + \sa setPrintRange(), printRange(), QAbstractPrintDialog::PrintRange */ /*! @@ -594,21 +594,6 @@ void QPrinterPrivate::setProperty(QPrintEngine::PrintEnginePropertyKey key, cons the printer. */ - -/* - \enum QPrinter::PrintRange - - This enum is used to specify which print range the application - should use to print. - - \value AllPages All the pages should be printed. - \value Selection Only the selection should be printed. - \value PageRange Print according to the from page and to page options. - \value CurrentPage Only the current page should be printed. - - \sa setPrintRange(), printRange() -*/ - /*! Creates a new printer object with the given \a mode. */ -- cgit v1.2.3 From 13171e7e63bc5199d783e33decf7f402019d05cc Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 17 Mar 2014 21:18:05 +0200 Subject: Fix build on older MinGW versions > In constructor 'QWindowsPrintDevice::QWindowsPrintDevice(const QString&)': > src\plugins\printsupport\windows\qwindowsprintdevice.cpp:105:86: > error: 'DC_COLLATE' was not declared in this scope Change-Id: Ifb64c323765ae4b6abb80c32d4ba2bc3fbffa245 Reviewed-by: John Layt --- src/plugins/printsupport/windows/qwindowsprintdevice.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index fce4bbb42b..1b55937ec7 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -43,6 +43,10 @@ #include +#ifndef DC_COLLATE +# define DC_COLLATE 22 +#endif + QT_BEGIN_NAMESPACE #ifndef QT_NO_PRINTER -- cgit v1.2.3 From 433ebd1628a087497af2b3c01a3ff512c3c150ee Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 17 Mar 2014 12:33:32 +0100 Subject: AVX image code was removed Remove a last left-over after 5e519b31dceff1fbb0a7ac5eeb5f6e071c1b6ef7 Change-Id: I85e73a5d81d45b4ccfc80cdaf34ab7b6c3c85bdc Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Thiago Macieira --- src/gui/image/qjpeghandler.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index bd358b7228..5008b1982b 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -856,7 +856,6 @@ bool QJpegHandlerPrivate::read(QImage *image) Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len); Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len); -Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_avx(quint32 *dst, const uchar *src, int len); QJpegHandler::QJpegHandler() : d(new QJpegHandlerPrivate(this)) -- cgit v1.2.3 From 68a9229a97d358639357f76cfb186bb61aa6ce92 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 21 Feb 2014 09:58:32 +0100 Subject: Android input method improvements Use the new inputmethod query API. and get rid of the hack where we would move the cursor back and forwards to make sure that the Android software keyboard noticed that the cursor had moved. The android plugin now uses absolute positions instead of position within the paragraph for all cursor handling (provided that the control supports the new API). Task-number: QTBUG-37511 Change-Id: I03463dbbcb4acbfa41e2eab06889d021d50da01f Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qtproject/qt5/android/QtActivityDelegate.java | 2 + .../qtproject/qt5/android/QtInputConnection.java | 1 + src/plugins/platforms/android/androidjniinput.cpp | 17 ----- .../platforms/android/qandroidinputcontext.cpp | 86 ++++++++++++++++++---- .../platforms/android/qandroidinputcontext.h | 7 +- src/widgets/widgets/qplaintextedit.cpp | 9 ++- src/widgets/widgets/qplaintextedit.h | 1 + 7 files changed, 88 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index aa18dfc2d1..ea8e5cd44c 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -301,6 +301,8 @@ public class QtActivityDelegate protected void onReceiveResult(int resultCode, Bundle resultData) { switch (resultCode) { case InputMethodManager.RESULT_SHOWN: + QtNativeInputConnection.updateCursorPosition(); + //FALLTHROUGH case InputMethodManager.RESULT_UNCHANGED_SHOWN: setKeyboardVisibility(true); break; diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java index 4b2d50ca1f..5fdeb12c15 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java @@ -78,6 +78,7 @@ class QtNativeInputConnection static native boolean copy(); static native boolean copyURL(); static native boolean paste(); + static native boolean updateCursorPosition(); } class HideKeyboardRunnable implements Runnable { diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 9d605c7a17..9efdcad158 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -67,8 +67,6 @@ namespace QtAndroidInput static QPointer m_mouseGrabber; - static int m_lastCursorPos = -1; - void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd) { AttachedJNIEnv env; @@ -78,21 +76,6 @@ namespace QtAndroidInput #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd; #endif - if (candidatesStart == -1 && candidatesEnd == -1 && selStart == selEnd) { - // Qt only gives us position inside the block, so if we move to the - // same position in another block, the Android keyboard will believe - // we have not changed position, and be terribly confused. - if (selStart == m_lastCursorPos) { -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << ">>> FAKEUPDATESELECTION" << selStart+1; -#endif - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID, - selStart+1, selEnd+1, candidatesStart, candidatesEnd); - } - m_lastCursorPos = selStart; - } else { - m_lastCursorPos = -1; - } env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID, selStart, selEnd, candidatesStart, candidatesEnd); } diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 326972e71e..bfb13811e3 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -81,7 +81,7 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new env->ReleaseStringChars(text, jstr); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ COMMIT" << str; + qDebug() << "@@@ COMMIT" << str << newCursorPosition; #endif return m_androidInputContext->commitText(str, newCursorPosition); } @@ -160,7 +160,7 @@ static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, ji const QString &text = m_androidInputContext->getTextAfterCursor(length, flags); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ GET" << length << text; + qDebug() << "@@@ GETA" << length << text; #endif return env->NewString(reinterpret_cast(text.constData()), jsize(text.length())); } @@ -172,7 +172,7 @@ static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, j const QString &text = m_androidInputContext->getTextBeforeCursor(length, flags); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ GET" << length << text; + qDebug() << "@@@ GETB" << length << text; #endif return env->NewString(reinterpret_cast(text.constData()), jsize(text.length())); } @@ -188,7 +188,7 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji env->ReleaseStringChars(text, jstr); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ SET" << str; + qDebug() << "@@@ SET" << str << newCursorPosition; #endif return m_androidInputContext->setComposingText(str, newCursorPosition); } @@ -271,6 +271,18 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/) return m_androidInputContext->paste(); } +static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/) +{ + if (!m_androidInputContext) + return JNI_FALSE; + +#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL + qDebug() << "@@@ UPDATECURSORPOS"; +#endif + m_androidInputContext->updateCursorPosition(); + return true; +} + static JNINativeMethod methods[] = { {"commitText", "(Ljava/lang/String;I)Z", (void *)commitText}, @@ -288,7 +300,8 @@ static JNINativeMethod methods[] = { {"cut", "()Z", (void *)cut}, {"copy", "()Z", (void *)copy}, {"copyURL", "()Z", (void *)copyURL}, - {"paste", "()Z", (void *)paste} + {"paste", "()Z", (void *)paste}, + {"updateCursorPosition", "()Z", (void *)updateCursorPosition} }; @@ -404,7 +417,9 @@ void QAndroidInputContext::updateCursorPosition() { QSharedPointer query = focusObjectInputMethodQuery(); if (!query.isNull() && !m_blockUpdateSelection) { - const int cursorPos = query->value(Qt::ImCursorPosition).toInt(); + // make sure it also works with editors that have not been updated to the new API + QVariant absolutePos = query->value(Qt::ImAbsolutePosition); + const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt(); QtAndroidInput::updateSelection(cursorPos, cursorPos, -1, -1); //selection empty and no pre-edit text } } @@ -422,9 +437,9 @@ void QAndroidInputContext::invokeAction(QInputMethod::Action action, int cursorP #warning TODO Handle at least QInputMethod::ContextMenu action Q_UNUSED(action) Q_UNUSED(cursorPosition) - - if (action == QInputMethod::Click) - commit(); + //### click should be passed to the IM, but in the meantime it's better to ignore it than to do something wrong + // if (action == QInputMethod::Click) + // commit(); } QRectF QAndroidInputContext::keyboardRect() const @@ -573,6 +588,12 @@ QString QAndroidInputContext::getSelectedText(jint /*flags*/) QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/) { + QVariant textAfter = queryFocusObjectThreadSafe(Qt::ImTextAfterCursor, QVariant(length)); + if (textAfter.isValid()) { + return textAfter.toString().left(length); + } + + //compatibility code for old controls that do not implement the new API QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return QString(); @@ -587,15 +608,21 @@ QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/) QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/) { + QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length)); + if (textBefore.isValid()) { + return textBefore.toString().left(length); + } + + //compatibility code for old controls that do not implement the new API QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return QString(); + int cursorPos = query->value(Qt::ImCursorPosition).toInt(); QString text = query->value(Qt::ImSurroundingText).toString(); if (!text.length()) return text; - int cursorPos = query->value(Qt::ImCursorPosition).toInt(); const int wordLeftPos = cursorPos - length; return text.mid(wordLeftPos > 0 ? wordLeftPos : 0, cursorPos); } @@ -621,8 +648,9 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur QSharedPointer query = focusObjectInputMethodQuery(); if (!query.isNull() && !m_blockUpdateSelection) { - int cursorPos = query->value(Qt::ImCursorPosition).toInt(); - int preeditLength = text.length(); + QVariant absolutePos = query->value(Qt::ImAbsolutePosition); + const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt(); + const int preeditLength = text.length(); QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, cursorPos, cursorPos+preeditLength); } @@ -650,16 +678,19 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end) Therefore, the length of the region is end - start */ int length = end - start; + int localPos = query->value(Qt::ImCursorPosition).toInt(); + QVariant absolutePos = query->value(Qt::ImAbsolutePosition); + int blockPosition = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0; + int localStart = start - blockPosition; // Qt uses position inside block bool updateSelectionWasBlocked = m_blockUpdateSelection; m_blockUpdateSelection = true; QString text = query->value(Qt::ImSurroundingText).toString(); - m_composingText = text.mid(start, length); + m_composingText = text.mid(localStart, length); - //in the Qt text controls, cursor pos is the start of the preedit - int cursorPos = query->value(Qt::ImCursorPosition).toInt(); - int relativeStart = start - cursorPos; + //in the Qt text controls, the cursor position is the start of the preedit + int relativeStart = localStart - localPos; QList attributes; @@ -669,6 +700,9 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end) attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, length, QVariant(underlined))); + // Keep the cursor position unchanged (don't move to end of preedit) + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, localPos - localStart, length, QVariant())); + QInputMethodEvent event(m_composingText, attributes); event.setCommitString(QString(), relativeStart, length); sendInputMethodEvent(&event); @@ -720,6 +754,26 @@ jboolean QAndroidInputContext::paste() return JNI_FALSE; } + +Q_INVOKABLE QVariant QAndroidInputContext::queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument) +{ + return QInputMethod::queryFocusObject(query, argument); +} + +QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument) +{ + bool inMainThread = qGuiApp->thread() == QThread::currentThread(); + QVariant retval; + + QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe", + inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVariant, retval), + Q_ARG(Qt::InputMethodQuery, query), + Q_ARG(QVariant, argument)); + + return retval; +} + QSharedPointer QAndroidInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries) { #warning TODO make qGuiApp->focusObject() thread safe !!! diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h index 041bd0dc49..2fb54a97c4 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.h +++ b/src/plugins/platforms/android/qandroidinputcontext.h @@ -114,14 +114,19 @@ public: jboolean copyURL(); jboolean paste(); +public slots: + void updateCursorPosition(); + private: QSharedPointer focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll); void sendInputMethodEvent(QInputMethodEvent *event); + Q_INVOKABLE QVariant queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument); + QVariant queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument); + private slots: virtual void sendEvent(QObject *receiver, QInputMethodEvent *event); virtual void sendEvent(QObject *receiver, QInputMethodQueryEvent *event); - void updateCursorPosition(); private: ExtractedText m_extractedText; diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index d51dce4765..beb44e602e 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -2184,6 +2184,13 @@ void QPlainTextEdit::scrollContentsBy(int dx, int /*dy*/) /*!\reimp */ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const +{ + return inputMethodQuery(property, QVariant()); +} + +/*!\internal + */ +QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const { Q_D(const QPlainTextEdit); QVariant v; @@ -2192,7 +2199,7 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const v = QWidget::inputMethodQuery(property); break; default: - v = d->control->inputMethodQuery(property, QVariant()); + v = d->control->inputMethodQuery(property, argument); const QPoint offset(-d->horizontalOffset(), -0); if (v.type() == QVariant::RectF) v = v.toRectF().toRect().translated(offset); diff --git a/src/widgets/widgets/qplaintextedit.h b/src/widgets/widgets/qplaintextedit.h index 1fb4625fb1..54cd3e14ed 100644 --- a/src/widgets/widgets/qplaintextedit.h +++ b/src/widgets/widgets/qplaintextedit.h @@ -185,6 +185,7 @@ public: int blockCount() const; QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const; public Q_SLOTS: -- cgit v1.2.3 From 3245745cd0d843a8927dbc2015b8f3f416a41cdb Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 14 Mar 2014 17:33:28 +0100 Subject: Handle key release events correctly Ignore key events that we don't actually handle. Task-number: QTBUG-35784 Change-Id: I196a4d0d199817a7dfd32fc98207ebfe3982050b Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/widgets/widgets/qplaintextedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index beb44e602e..6ed1aeff72 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -1810,7 +1810,7 @@ void QPlainTextEdit::keyReleaseEvent(QKeyEvent *e) } } #else - Q_UNUSED(e); + QWidget::keyReleaseEvent(e); #endif } -- cgit v1.2.3 From 336cb75d8f1de45215ed6e871cc5121a3e12c111 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 10 Mar 2014 16:38:38 +0100 Subject: X11: defaultDragDistance depends on screen resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The usual default is 10 pixels, but on a screen with resolution exceeding 100 DPI, it will be a proportionally larger number. The reason is that such precise finger and mouse movements are more difficult on higher-resolution screens. Change-Id: I6e66299e12e6cac5c4e032251b32a34940970372 Reviewed-by: Jørgen Lind Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbintegration.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index aaa2e81c40..0bab341914 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -396,7 +396,6 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const case QPlatformIntegration::CursorFlashTime: case QPlatformIntegration::KeyboardInputInterval: case QPlatformIntegration::MouseDoubleClickInterval: - case QPlatformIntegration::StartDragDistance: case QPlatformIntegration::StartDragTime: case QPlatformIntegration::KeyboardAutoRepeatRate: case QPlatformIntegration::PasswordMaskDelay: @@ -406,6 +405,20 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const case QPlatformIntegration::PasswordMaskCharacter: // TODO using various xcb, gnome or KDE settings break; // Not implemented, use defaults + case QPlatformIntegration::StartDragDistance: { + // The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but + // on a high-resolution screen it makes sense to increase it. + const QList &screens = defaultConnection()->screens(); + qreal dpi = 100.0; + if (screens.length() > 0) { + const QXcbScreen *screen = screens.at(defaultConnection()->primaryScreen()); + if (screen->logicalDpi().first > dpi) + dpi = screen->logicalDpi().first; + if (screen->logicalDpi().second > dpi) + dpi = screen->logicalDpi().second; + } + return 10.0 * dpi / 100.0; + } case QPlatformIntegration::ShowIsFullScreen: // X11 always has support for windows, but the // window manager could prevent it (e.g. matchbox) -- cgit v1.2.3 From 9827f6d19817d2653ea4fbf5df30d7bb2fb6f787 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sat, 15 Mar 2014 16:49:22 +0200 Subject: WinRT: Load system fonts using DirectWrite System-installed TrueType fonts can be read into memory and loaded into the FreeType font engine. This allows the application to be packaged without fonts, but does not work on Windows Phone where DirectWrite is not supported. Every single-file TrueType font is registered with the font database, and then loaded into memory at the point that the font is actually used. Task-number: QTBUG-37230 Change-Id: I804116e37a874cd146a0653ba4cc018f8b1cd6a4 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 314 ++++++++++++++++++++- src/plugins/platforms/winrt/qwinrtfontdatabase.h | 19 ++ src/plugins/platforms/winrt/winrt.pro | 5 + 3 files changed, 337 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index c7fa339fad..3da87de708 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -44,6 +44,14 @@ #include #include +#ifndef Q_OS_WINPHONE +#include +#include +#include +#include +using namespace Microsoft::WRL; +#endif // !Q_OS_WINPHONE + QT_BEGIN_NAMESPACE QString QWinRTFontDatabase::fontDir() const @@ -54,11 +62,315 @@ QString QWinRTFontDatabase::fontDir() const const QString applicationDirPath = QCoreApplication::applicationDirPath(); fontDirectory = applicationDirPath + QLatin1String("/fonts"); if (!QFile::exists(fontDirectory)) { - qWarning("No fonts directory found in application package."); +#ifndef Q_OS_WINPHONE + if (m_fonts.isEmpty()) +#endif + qWarning("No fonts directory found in application package."); fontDirectory = applicationDirPath; } } return fontDirectory; } +#ifndef Q_OS_WINPHONE + +QWinRTFontDatabase::~QWinRTFontDatabase() +{ + foreach (IDWriteFontFile *fontFile, m_fonts.keys()) + fontFile->Release(); +} + +QFont QWinRTFontDatabase::defaultFont() const +{ + return QFont(QStringLiteral("Segoe UI")); +} + +void QWinRTFontDatabase::populateFontDatabase() +{ + ComPtr factory; + HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory); + if (FAILED(hr)) { + qWarning("Failed to create DirectWrite factory: %s", qPrintable(qt_error_string(hr))); + QBasicFontDatabase::populateFontDatabase(); + return; + } + + ComPtr fontCollection; + hr = factory->GetSystemFontCollection(&fontCollection); + if (FAILED(hr)) { + qWarning("Failed to open system font collection: %s", qPrintable(qt_error_string(hr))); + QBasicFontDatabase::populateFontDatabase(); + return; + } + + int fontFamilyCount = fontCollection->GetFontFamilyCount(); + for (int i = 0; i < fontFamilyCount; ++i) { + ComPtr fontFamily; + hr = fontCollection->GetFontFamily(i, &fontFamily); + if (FAILED(hr)) { + qWarning("Unable to get font family: %s", qPrintable(qt_error_string(hr))); + continue; + } + + ComPtr names; + hr = fontFamily->GetFamilyNames(&names); + if (FAILED(hr)) { + qWarning("Unable to get font family names: %s", qPrintable(qt_error_string(hr))); + continue; + } + quint32 familyNameLength; + hr = names->GetStringLength(0, &familyNameLength); + if (FAILED(hr)) { + qWarning("Unable to get family name length: %s", qPrintable(qt_error_string(hr))); + continue; + } + QVector familyBuffer(familyNameLength + 1); + hr = names->GetString(0, familyBuffer.data(), familyBuffer.size()); + if (FAILED(hr)) { + qWarning("Unable to create font family name: %s", qPrintable(qt_error_string(hr))); + continue; + } + QString familyName = QString::fromWCharArray(familyBuffer.data(), familyNameLength); + + int fontCount = fontFamily->GetFontCount(); + for (int j = 0; j < fontCount; ++j) { + ComPtr font; + hr = fontFamily->GetFont(j, &font); + if (FAILED(hr)) { + qWarning("Unable to get base font: %s", qPrintable(qt_error_string(hr))); + continue; + } + + ComPtr baseFontFace; + hr = font->CreateFontFace(&baseFontFace); + if (FAILED(hr)) { + qWarning("Unable to create base font face: %s", qPrintable(qt_error_string(hr))); + continue; + } + ComPtr fontFace; + hr = baseFontFace.As(&fontFace); + if (FAILED(hr)) { + qWarning("Unable to create font face: %s", qPrintable(qt_error_string(hr))); + continue; + } + + // Only try to load true-type fonts + DWRITE_FONT_FACE_TYPE type = fontFace->GetType(); + if (!(type == DWRITE_FONT_FACE_TYPE_TRUETYPE + || type == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)) { + continue; + } + + // We can't deal with multi-file fonts + quint32 fileCount; + hr = fontFace->GetFiles(&fileCount, NULL); + if (FAILED(hr)) { + qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr))); + continue; + } + if (fileCount != 1) // Should not happen as we only look at TT fonts + continue; + + ComPtr informationalStrings; + BOOL exists; + hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_MANUFACTURER, + &informationalStrings, &exists); + if (FAILED(hr)) { + qWarning("Unable to get font foundry: %s", qPrintable(qt_error_string(hr))); + continue; + } + QString foundryName; + if (exists) { + quint32 length; + hr = informationalStrings->GetStringLength(0, &length); + if (FAILED(hr)) + qWarning("Unable to get foundry name length: %s", qPrintable(qt_error_string(hr))); + if (SUCCEEDED(hr)) { + QVector buffer(length + 1); + hr = informationalStrings->GetString(0, buffer.data(), buffer.size()); + if (FAILED(hr)) + qWarning("Unable to get foundry name: %s", qPrintable(qt_error_string(hr))); + if (SUCCEEDED(hr)) + foundryName = QString::fromWCharArray(buffer.data(), length); + } + } + + QFont::Weight weight; + switch (font->GetWeight()) { + case DWRITE_FONT_WEIGHT_THIN: + case DWRITE_FONT_WEIGHT_EXTRA_LIGHT: + case DWRITE_FONT_WEIGHT_LIGHT: + case DWRITE_FONT_WEIGHT_SEMI_LIGHT: + weight = QFont::Light; + break; + default: + case DWRITE_FONT_WEIGHT_NORMAL: + case DWRITE_FONT_WEIGHT_MEDIUM: + weight = QFont::Normal; + break; + case DWRITE_FONT_WEIGHT_DEMI_BOLD: + weight = QFont::DemiBold; + break; + case DWRITE_FONT_WEIGHT_BOLD: + case DWRITE_FONT_WEIGHT_EXTRA_BOLD: + weight = QFont::Bold; + break; + case DWRITE_FONT_WEIGHT_BLACK: + case DWRITE_FONT_WEIGHT_EXTRA_BLACK: + weight = QFont::Black; + break; + } + + QFont::Style style; + switch (font->GetStyle()) { + default: + case DWRITE_FONT_STYLE_NORMAL: + style = QFont::StyleNormal; + break; + case DWRITE_FONT_STYLE_OBLIQUE: + style = QFont::StyleOblique; + break; + case DWRITE_FONT_STYLE_ITALIC: + style = QFont::StyleItalic; + break; + } + + QFont::Stretch stretch; + switch (font->GetStretch()) { + default: + case DWRITE_FONT_STRETCH_UNDEFINED: + case DWRITE_FONT_STRETCH_NORMAL: + stretch = QFont::Unstretched; + break; + case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: + stretch = QFont::UltraCondensed; + break; + case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: + stretch = QFont::ExtraCondensed; + break; + case DWRITE_FONT_STRETCH_CONDENSED: + stretch = QFont::Condensed; + break; + case DWRITE_FONT_STRETCH_SEMI_CONDENSED: + stretch = QFont::SemiCondensed; + break; + case DWRITE_FONT_STRETCH_SEMI_EXPANDED: + stretch = QFont::SemiExpanded; + break; + case DWRITE_FONT_STRETCH_EXPANDED: + stretch = QFont::Expanded; + break; + case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: + stretch = QFont::ExtraExpanded; + break; + case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: + stretch = QFont::UltraExpanded; + break; + } + + const bool fixedPitch = fontFace->IsMonospacedFont(); + + quint32 unicodeRange[4]; + quint32 actualRangeCount; + hr = fontFace->GetUnicodeRanges( + 2, reinterpret_cast(unicodeRange), &actualRangeCount); + if (FAILED(hr) && hr != E_NOT_SUFFICIENT_BUFFER) { // Ignore insufficient buffer; we only need 4 indices + qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr))); + continue; + } + quint32 codePageRange[2] = { 0, 0 }; + QSupportedWritingSystems writingSystems = + QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + + IDWriteFontFile *fontFile; + hr = fontFace->GetFiles(&fileCount, &fontFile); + if (FAILED(hr)) { + qWarning("Unable to get font file: %s", qPrintable(qt_error_string(hr))); + continue; + } + + FontDescription description = { fontFace->GetIndex(), QUuid::createUuid().toByteArray() }; + m_fonts.insert(fontFile, description); + registerFont(familyName, QString(), foundryName, weight, style, stretch, + true, true, 0, fixedPitch, writingSystems, fontFile); + } + } + + QBasicFontDatabase::populateFontDatabase(); +} + +QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) +{ + IDWriteFontFile *fontFile = reinterpret_cast(handle); + if (!m_fonts.contains(fontFile)) + return QBasicFontDatabase::fontEngine(fontDef, handle); + + const void *referenceKey; + quint32 referenceKeySize; + HRESULT hr = fontFile->GetReferenceKey(&referenceKey, &referenceKeySize); + if (FAILED(hr)) { + qWarning("Unable to get font file reference key: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + ComPtr loader; + hr = fontFile->GetLoader(&loader); + if (FAILED(hr)) { + qWarning("Unable to get font file loader: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + ComPtr stream; + hr =loader->CreateStreamFromKey(referenceKey, referenceKeySize, &stream); + if (FAILED(hr)) { + qWarning("Unable to get font file stream: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + quint64 fileSize; + hr = stream->GetFileSize(&fileSize); + if (FAILED(hr)) { + qWarning("Unable to get font file size: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + const void *data; + void *context; + hr = stream->ReadFileFragment(&data, 0, fileSize, &context); + if (FAILED(hr)) { + qWarning("Unable to get font file data: %s", qPrintable(qt_error_string(hr))); + return 0; + } + const QByteArray fontData((const char *)data, fileSize); + stream->ReleaseFileFragment(context); + + QFontEngine::FaceId faceId; + const FontDescription description = m_fonts.value(fontFile); + faceId.uuid = description.uuid; + faceId.index = description.index; + const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + QFontEngineFT *engine = new QFontEngineFT(fontDef); + if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { + delete engine; + return 0; + } + + return engine; +} + +void QWinRTFontDatabase::releaseHandle(void *handle) +{ + IDWriteFontFile *fontFile = reinterpret_cast(handle); + if (m_fonts.contains(fontFile)) { + m_fonts.remove(fontFile); + fontFile->Release(); + return; + } + + QBasicFontDatabase::releaseHandle(handle); +} + +#endif // !Q_OS_WINPHONE + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index 49e32470c2..6f194a10cc 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -46,10 +46,29 @@ QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINPHONE +struct IDWriteFontFile; + +struct FontDescription +{ + quint32 index; + QByteArray uuid; +}; +#endif + class QWinRTFontDatabase : public QBasicFontDatabase { public: QString fontDir() const; +#ifndef Q_OS_WINPHONE + ~QWinRTFontDatabase(); + QFont defaultFont() const Q_DECL_OVERRIDE; + void populateFontDatabase() Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + void releaseHandle(void *handle) Q_DECL_OVERRIDE; +private: + QHash m_fonts; +#endif // !Q_OS_WINPHONE }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 6e3cfb1d20..306bbc8174 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -11,6 +11,11 @@ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES LIBS += $$QMAKE_LIBS_CORE +!winphone { + LIBS += -ldwrite + INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include +} + SOURCES = \ main.cpp \ qwinrtbackingstore.cpp \ -- cgit v1.2.3 From b63027867e6054da871c89a22b446730553872a2 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sun, 16 Mar 2014 20:28:39 +0200 Subject: WinRT: Fix QDesktopServices::openUrl() for local files The passed-in URL is expected to be a file-scheme URL to be converted to a QString using toLocalFile(), not a relative path to be prepended with the application directory. Change-Id: I647f351c99f0df66ef017936585f044292c16aff Reviewed-by: Maurice Kalinowski Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtservices.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp index 8f0a1d55bb..73c090351b 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.cpp +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -106,8 +106,7 @@ bool QWinRTServices::openDocument(const QUrl &url) if (!(m_fileFactory && m_launcher)) return QPlatformServices::openDocument(url); - QString pathString = QDir::toNativeSeparators( - QDir::cleanPath(qApp->applicationDirPath().append(url.toString(QUrl::RemoveScheme)))); + const QString pathString = QDir::toNativeSeparators(url.toLocalFile()); HSTRING_HEADER header; HSTRING path; WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path); IAsyncOperation *fileOp; -- cgit v1.2.3 From a1af25290bbd078628e362d4b704a047853d620c Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 17 Mar 2014 19:12:16 +0100 Subject: Accessibility Mac: fix role for links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ied4dd0bf112f36065da4063857898ca4bd0eb77b Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaaccessibility.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 1371eb3658..0f99a414a0 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -130,7 +130,7 @@ static void populateRoleMap() roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole; roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole; roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole; - roleMap[QAccessible::Link] = NSAccessibilityTextFieldRole; + roleMap[QAccessible::Link] = NSAccessibilityLinkRole; roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole; roleMap[QAccessible::Splitter] = NSAccessibilitySplitGroupRole; roleMap[QAccessible::List] = NSAccessibilityListRole; -- cgit v1.2.3 From 4fc3d9ba6301a8c28a1f4ddf1665b0fe49ce092d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 18 Mar 2014 13:49:44 +0100 Subject: Fix double release in QTimeZone on Mac availableTimeZoneIds would release the enumerator. This leads to a double free, so simply don't release the enumerator. Task-number: QTBUG-37582 Change-Id: I521a9555d32545afd47095235ccee75a4f3e1974 Reviewed-by: Gabriel de Dietrich --- src/corelib/tools/qtimezoneprivate_mac.mm | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index 3d95377850..49930490ff 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -272,7 +272,6 @@ QSet QMacTimeZonePrivate::availableTimeZoneIds() const tzid = QCFString::toQString([enumerator nextObject]).toUtf8(); } - [enumerator release]; return set; } -- cgit v1.2.3 From ea057c83720abd0c3c57d9dab91a5ad704b158d3 Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Mon, 17 Mar 2014 12:04:40 +0100 Subject: QNX: Fix QToolTip The problem is that on QNX the window activation and focus events are delayed. QToolTip can not handle this and would hide the tool tip right after it is created. Change-Id: I6045d1d277b73508c24174d72a05e0baa4ae6e7f Reviewed-by: Rafael Roquetto --- src/widgets/kernel/qtooltip.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index c898f56015..5aea55e196 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -322,13 +322,32 @@ bool QTipLabel::eventFilter(QObject *o, QEvent *e) case QEvent::Leave: hideTip(); break; + + +#if defined (Q_OS_QNX) // On QNX the window activate and focus events are delayed and will appear + // after the window is shown. + case QEvent::WindowActivate: + case QEvent::FocusIn: + return false; + case QEvent::WindowDeactivate: + if (o != this) + return false; + hideTipImmediately(); + break; + case QEvent::FocusOut: + if (reinterpret_cast(o) != windowHandle()) + return false; + hideTipImmediately(); + break; +#else case QEvent::WindowActivate: case QEvent::WindowDeactivate: + case QEvent::FocusIn: + case QEvent::FocusOut: +#endif case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: - case QEvent::FocusIn: - case QEvent::FocusOut: case QEvent::Wheel: hideTipImmediately(); break; -- cgit v1.2.3 From 4059e586cc5cebd7b747f8428c8d018812c7c519 Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Wed, 12 Mar 2014 15:59:47 +0100 Subject: QNX: Remove sending synchronous window system events This makes some OpenGL autotests fail. Apparently we are sending a expose event before the window is properly exposed. Change-Id: I1710ec51605088ce594fc4676214db2d822d1cc5 Reviewed-by: Kevin Krammer Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qqnxwindow.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index e43aaa83e8..95b6c904f2 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -247,14 +247,8 @@ void QQnxWindow::setGeometry(const QRect &rect) setGeometryHelper(newGeometry); - // Send a geometry change event to Qt (triggers resizeEvent() in QWindow/QWidget). - - // Calling flushWindowSystemEvents() here would flush input events which - // could result in re-entering QQnxWindow::setGeometry() again. - QWindowSystemInterface::setSynchronousWindowsSystemEvents(true); QWindowSystemInterface::handleGeometryChange(window(), newGeometry); QWindowSystemInterface::handleExposeEvent(window(), newGeometry); - QWindowSystemInterface::setSynchronousWindowsSystemEvents(false); } void QQnxWindow::setGeometryHelper(const QRect &rect) -- cgit v1.2.3 From 1fad6a2483d1283e4eeef310f6ebf5fe5a2011e0 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Tue, 18 Mar 2014 13:10:34 +0100 Subject: update bundled sqlite to 3.8.4.1 The "Fixed CE build of sqlite3" patch is preserved in this change. (ea70ec8711af45128d63634a01dfc4c1a51ac331) Change-Id: I9cf211785071386173a87f645773cdae08498354 Reviewed-by: Friedemann Kleint Reviewed-by: Mark Brand --- src/3rdparty/sqlite/shell.c | 344 +- src/3rdparty/sqlite/sqlite3.c | 13910 ++++++++++++++++++++++------------------ src/3rdparty/sqlite/sqlite3.h | 100 +- 3 files changed, 7894 insertions(+), 6460 deletions(-) (limited to 'src') diff --git a/src/3rdparty/sqlite/shell.c b/src/3rdparty/sqlite/shell.c index 480ec5b455..2cff102e91 100644 --- a/src/3rdparty/sqlite/shell.c +++ b/src/3rdparty/sqlite/shell.c @@ -45,14 +45,17 @@ # include #endif -#ifdef HAVE_EDITLINE -# include -#endif -#if defined(HAVE_READLINE) && HAVE_READLINE==1 +#if defined(HAVE_READLINE) && HAVE_READLINE!=0 # include # include +#else +# undef HAVE_READLINE +#endif +#if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE) +# define HAVE_READLINE 1 +# include #endif -#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1) +#if !defined(HAVE_READLINE) # define add_history(X) # define read_history(X) # define write_history(X) @@ -62,7 +65,9 @@ #if defined(_WIN32) || defined(WIN32) # include #define isatty(h) _isatty(h) -#define access(f,m) _access((f),(m)) +#ifndef access +# define access(f,m) _access((f),(m)) +#endif #undef popen #define popen _popen #undef pclose @@ -413,7 +418,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ zResult = local_getline(zPrior, in); }else{ zPrompt = isContinuation ? continuePrompt : mainPrompt; -#if defined(HAVE_READLINE) && HAVE_READLINE==1 +#if defined(HAVE_READLINE) free(zPrior); zResult = readline(zPrompt); if( zResult && *zResult ) add_history(zResult); @@ -441,6 +446,7 @@ struct previous_mode_data { struct callback_data { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ + int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */ int statsOn; /* True to display memory stats before each finalize */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ @@ -597,6 +603,7 @@ static void output_c_string(FILE *out, const char *z){ */ static void output_html_string(FILE *out, const char *z){ int i; + if( z==0 ) z = ""; while( *z ){ for(i=0; z[i] && z[i]!='<' @@ -1004,7 +1011,7 @@ static int run_table_dump_query( int nResult; int i; const char *z; - rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0); + rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; @@ -1176,7 +1183,8 @@ static int str_in_array(const char *zStr, const char **azArray){ ** ** * For each "Goto", if the jump destination is earlier in the program ** and ends on one of: -** Yield SeekGt SeekLt RowSetRead +** Yield SeekGt SeekLt RowSetRead Rewind +** or if the P1 parameter is one instead of zero, ** then indent all opcodes between the earlier instruction ** and "Goto" by 2 spaces. */ @@ -1188,7 +1196,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ int iOp; /* Index of operation in p->aiIndent[] */ const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; - const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", 0 }; + const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", "Rewind", 0 }; const char *azGoto[] = { "Goto", 0 }; /* Try to figure out if this is really an EXPLAIN statement. If this @@ -1224,8 +1232,10 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ if( str_in_array(zOp, azNext) ){ for(i=p2op; iaiIndent[i] += 2; } - if( str_in_array(zOp, azGoto) && p2opnIndent && abYield[p2op] ){ - for(i=p2op; iaiIndent[i] += 2; + if( str_in_array(zOp, azGoto) && p2opnIndent + && (abYield[p2op] || sqlite3_column_int(pSql, 2)) + ){ + for(i=p2op+1; iaiIndent[i] += 2; } } @@ -1296,6 +1306,23 @@ static int shell_exec( fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); } + /* Show the EXPLAIN QUERY PLAN if .eqp is on */ + if( pArg && pArg->autoEQP ){ + sqlite3_stmt *pExplain; + char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt)); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + while( sqlite3_step(pExplain)==SQLITE_ROW ){ + fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0)); + fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); + fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); + fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); + } + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); + } + /* Output TESTCTRL_EXPLAIN text of requested */ if( pArg && pArg->mode==MODE_Explain ){ const char *zExplain = 0; @@ -1452,7 +1479,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ zTableInfo = appendText(zTableInfo, zTable, '"'); zTableInfo = appendText(zTableInfo, ");", 0); - rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); + rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); free(zTableInfo); if( rc!=SQLITE_OK || !pTableInfo ){ return 1; @@ -1542,6 +1569,7 @@ static int run_schema_dump_query( static char zHelp[] = ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail ON|OFF Stop after hitting an error. Default OFF\n" + ".clone NEWDB Clone data into NEWDB from the existing database\n" ".databases List names and files of attached databases\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" @@ -1581,6 +1609,7 @@ static char zHelp[] = ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" + ".save FILE Write in-memory database into FILE\n" ".schema ?TABLE? Show the CREATE statements\n" " If TABLE specified, only show tables matching\n" " LIKE pattern TABLE.\n" @@ -1836,7 +1865,7 @@ static void csv_append_char(CSVReader *p, int c){ ** + Report syntax errors on stderr */ static char *csv_read_one_field(CSVReader *p){ - int c, pc; + int c, pc, ppc; int cSep = p->cSeparator; p->n = 0; c = fgetc(p->in); @@ -1847,7 +1876,7 @@ static char *csv_read_one_field(CSVReader *p){ if( c=='"' ){ int startLine = p->nLine; int cQuote = c; - pc = 0; + pc = ppc = 0; while( 1 ){ c = fgetc(p->in); if( c=='\n' ) p->nLine++; @@ -1859,7 +1888,7 @@ static char *csv_read_one_field(CSVReader *p){ } if( (c==cSep && pc==cQuote) || (c=='\n' && pc==cQuote) - || (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote) + || (c=='\n' && pc=='\r' && ppc==cQuote) || (c==EOF && pc==cQuote) ){ do{ p->n--; }while( p->z[p->n]!=cQuote ); @@ -1877,6 +1906,7 @@ static char *csv_read_one_field(CSVReader *p){ break; } csv_append_char(p, c); + ppc = pc; pc = c; } }else{ @@ -1886,7 +1916,7 @@ static char *csv_read_one_field(CSVReader *p){ } if( c=='\n' ){ p->nLine++; - if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; + if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; } p->cTerm = c; } @@ -1894,6 +1924,219 @@ static char *csv_read_one_field(CSVReader *p){ return p->z; } +/* +** Try to transfer data for table zTable. If an error is seen while +** moving forward, try to go backwards. The backwards movement won't +** work for WITHOUT ROWID tables. +*/ +static void tryToCloneData( + struct callback_data *p, + sqlite3 *newDb, + const char *zTable +){ + sqlite3_stmt *pQuery = 0; + sqlite3_stmt *pInsert = 0; + char *zQuery = 0; + char *zInsert = 0; + int rc; + int i, j, n; + int nTable = (int)strlen(zTable); + int k = 0; + int cnt = 0; + const int spinRate = 10000; + + zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Error %d: %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_data_xfer; + } + n = sqlite3_column_count(pQuery); + zInsert = sqlite3_malloc(200 + nTable + n*3); + if( zInsert==0 ){ + fprintf(stderr, "out of memory\n"); + goto end_data_xfer; + } + sqlite3_snprintf(200+nTable,zInsert, + "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); + i = (int)strlen(zInsert); + for(j=1; jdb, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable); + break; + } + } /* End for(k=0...) */ + +end_data_xfer: + sqlite3_finalize(pQuery); + sqlite3_finalize(pInsert); + sqlite3_free(zQuery); + sqlite3_free(zInsert); +} + + +/* +** Try to transfer all rows of the schema that match zWhere. For +** each row, invoke xForEach() on the object defined by that row. +** If an error is encountered while moving forward through the +** sqlite_master table, try again moving backwards. +*/ +static void tryToCloneSchema( + struct callback_data *p, + sqlite3 *newDb, + const char *zWhere, + void (*xForEach)(struct callback_data*,sqlite3*,const char*) +){ + sqlite3_stmt *pQuery = 0; + char *zQuery = 0; + int rc; + const unsigned char *zName; + const unsigned char *zSql; + char *zErrMsg = 0; + + zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master" + " WHERE %s", zWhere); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_schema_xfer; + } + while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ + zName = sqlite3_column_text(pQuery, 0); + zSql = sqlite3_column_text(pQuery, 1); + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; + } + if( xForEach ){ + xForEach(p, newDb, (const char*)zName); + } + printf("done\n"); + } + if( rc!=SQLITE_DONE ){ + sqlite3_finalize(pQuery); + sqlite3_free(zQuery); + zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master" + " WHERE %s ORDER BY rowid DESC", zWhere); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + fprintf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_schema_xfer; + } + while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ + zName = sqlite3_column_text(pQuery, 0); + zSql = sqlite3_column_text(pQuery, 1); + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; + } + if( xForEach ){ + xForEach(p, newDb, (const char*)zName); + } + printf("done\n"); + } + } +end_schema_xfer: + sqlite3_finalize(pQuery); + sqlite3_free(zQuery); +} + +/* +** Open a new database file named "zNewDb". Try to recover as much information +** as possible out of the main database (which might be corrupt) and write it +** into zNewDb. +*/ +static void tryToClone(struct callback_data *p, const char *zNewDb){ + int rc; + sqlite3 *newDb = 0; + if( access(zNewDb,0)==0 ){ + fprintf(stderr, "File \"%s\" already exists.\n", zNewDb); + return; + } + rc = sqlite3_open(zNewDb, &newDb); + if( rc ){ + fprintf(stderr, "Cannot create output database: %s\n", + sqlite3_errmsg(newDb)); + }else{ + sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); + tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); + tryToCloneSchema(p, newDb, "type!='table'", 0); + sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); + } + sqlite3_close(newDb); +} + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -1936,7 +2179,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( nArg==0 ) return 0; /* no tokens, no error */ n = strlen30(azArg[0]); c = azArg[0][0]; - if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){ + if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) + || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) + ){ const char *zDestFile = 0; const char *zDb = 0; sqlite3 *pDest; @@ -2001,6 +2246,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ test_breakpoint(); }else + if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){ + tryToClone(p, azArg[1]); + }else + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ struct callback_data data; char *zErrMsg = 0; @@ -2073,6 +2322,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ p->echoOn = booleanValue(azArg[1]); }else + if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){ + p->autoEQP = booleanValue(azArg[1]); + }else + if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); rc = 2; @@ -2173,7 +2426,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ return 1; } nByte = strlen30(zSql); - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; @@ -2199,7 +2452,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ xCloser(sCsv.in); return 1; } - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); } sqlite3_free(zSql); if( rc ){ @@ -2226,7 +2479,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } zSql[j++] = ')'; zSql[j] = 0; - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); @@ -2645,6 +2898,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){ int i; fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); @@ -3037,7 +3291,10 @@ static int process_input(struct callback_data *p, FILE *in){ seenInterrupt = 0; } lineno++; - if( nSql==0 && _all_whitespace(zLine) ) continue; + if( nSql==0 && _all_whitespace(zLine) ){ + if( p->echoOn ) printf("%s\n", zLine); + continue; + } if( zLine && zLine[0]=='.' && nSql==0 ){ if( p->echoOn ) printf("%s\n", zLine); rc = do_meta_command(zLine, p); @@ -3099,6 +3356,7 @@ static int process_input(struct callback_data *p, FILE *in){ } nSql = 0; }else if( nSql && _all_whitespace(zSql) ){ + if( p->echoOn ) printf("%s\n", zSql); nSql = 0; } } @@ -3276,6 +3534,26 @@ static void main_init(struct callback_data *data) { sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); } +/* +** Output text to the console in a font that attracts extra attention. +*/ +#ifdef _WIN32 +static void printBold(const char *zText){ + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; + GetConsoleScreenBufferInfo(out, &defaultScreenInfo); + SetConsoleTextAttribute(out, + FOREGROUND_RED|FOREGROUND_INTENSITY + ); + printf("%s", zText); + SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); +} +#else +static void printBold(const char *zText){ + printf("\033[1m%s\033[0m", zText); +} +#endif + /* ** Get the argument to an --option. Throw an error and die if no argument ** is available. @@ -3296,12 +3574,15 @@ int main(int argc, char **argv){ char *zFirstCmd = 0; int i; int rc = 0; + int warnInmemoryDb = 0; +#if USE_SYSTEM_SQLITE+0!=1 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", sqlite3_sourceid(), SQLITE_SOURCE_ID); exit(1); } +#endif Argv0 = argv[0]; main_init(&data); stdin_is_interactive = isatty(0); @@ -3390,9 +3671,15 @@ int main(int argc, char **argv){ if( data.zDbFilename==0 ){ #ifndef SQLITE_OMIT_MEMORYDB data.zDbFilename = ":memory:"; + warnInmemoryDb = argc==1; #else fprintf(stderr,"%s: Error: no database filename specified\n", Argv0); return 1; +#endif +#ifdef SQLITE_SHELL_DBNAME_PROC + { extern void SQLITE_SHELL_DBNAME_PROC(const char**); + SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename); + warnInmemoryDb = 0; } #endif } data.out = stdout; @@ -3449,6 +3736,8 @@ int main(int argc, char **argv){ data.showHeader = 0; }else if( strcmp(z,"-echo")==0 ){ data.echoOn = 1; + }else if( strcmp(z,"-eqp")==0 ){ + data.autoEQP = 1; }else if( strcmp(z,"-stats")==0 ){ data.statsOn = 1; }else if( strcmp(z,"-bail")==0 ){ @@ -3526,10 +3815,15 @@ int main(int argc, char **argv){ int nHistory; printf( "SQLite version %s %.19s\n" /*extra-version-info*/ - "Enter \".help\" for instructions\n" - "Enter SQL statements terminated with a \";\"\n", + "Enter \".help\" for usage hints.\n", sqlite3_libversion(), sqlite3_sourceid() ); + if( warnInmemoryDb ){ + printf("Connected to a "); + printBold("transient in-memory database"); + printf(".\nUse \".open FILENAME\" to reopen on a " + "persistent database.\n"); + } zHome = find_home_dir(); if( zHome ){ nHistory = strlen30(zHome) + 20; @@ -3537,7 +3831,7 @@ int main(int argc, char **argv){ sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); } } -#if defined(HAVE_READLINE) && HAVE_READLINE==1 +#if defined(HAVE_READLINE) if( zHistory ) read_history(zHistory); #endif rc = process_input(&data, 0); diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c index 9c73927982..a2e37dd48e 100644 --- a/src/3rdparty/sqlite/sqlite3.c +++ b/src/3rdparty/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.8.2. By combining all the individual C code files into this +** version 3.8.4.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -25,6 +25,93 @@ #ifndef SQLITE_API # define SQLITE_API #endif +/************** Begin file sqliteInt.h ***************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** The previous paragraph was written in 2005. (This paragraph is written +** on 2008-11-28.) These days, all Linux kernels support large files, so +** you should probably leave LFS enabled. But some embedded platforms might +** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** For MinGW, check to see if we can include the header file containing its +** version information, among other things. Normally, this internal MinGW +** header file would [only] be included automatically by other MinGW header +** files; however, the contained version information is now required by this +** header file to work around binary compatibility issues (see below) and +** this is the only known way to reliably obtain it. This entire #if block +** would be completely unnecessary if there was any other way of detecting +** MinGW via their preprocessor (e.g. if they customized their GCC to define +** some MinGW-specific macros). When compiling for MinGW, either the +** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be +** defined; otherwise, detection of conditions specific to MinGW will be +** disabled. +*/ +#if defined(_HAVE_MINGW_H) +# include "mingw.h" +#elif defined(_HAVE__MINGW_H) +# include "_mingw.h" +#endif + +/* +** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T +** define is required to maintain binary compatibility with the MSVC runtime +** library in use (e.g. for Windows XP). +*/ +#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ + defined(_WIN32) && !defined(_WIN64) && \ + defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ + defined(__MSVCRT__) +# define _USE_32BIT_TIME_T +#endif + +/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear +** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for +** MinGW. +*/ +/************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ /* ** 2001 September 15 @@ -135,9 +222,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.8.2" -#define SQLITE_VERSION_NUMBER 3008002 -#define SQLITE_SOURCE_ID "2013-12-06 14:53:30 27392118af4c38c5203a04b8013e1afdb1cebd0d" +#define SQLITE_VERSION "3.8.4.1" +#define SQLITE_VERSION_NUMBER 3008004 +#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -519,6 +606,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) @@ -586,7 +674,8 @@ SQLITE_API int sqlite3_exec( ** after reboot following a crash or power loss, the only bytes in a ** file that were written at the application level might have changed ** and that adjacent bytes, even bytes within the same sector are -** guaranteed to be unchanged. +** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN +** flag indicate that a file cannot be deleted when open. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 @@ -817,15 +906,29 @@ struct sqlite3_io_methods { ** additional information. ** **
  • [[SQLITE_FCNTL_SYNC_OMITTED]] -** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by -** SQLite and sent to all VFSes in place of a call to the xSync method -** when the database connection has [PRAGMA synchronous] set to OFF.)^ -** Some specialized VFSes need this signal in order to operate correctly -** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most -** VFSes do not need this signal and should silently ignore this opcode. -** Applications should not call [sqlite3_file_control()] with this -** opcode as doing so may disrupt the operation of the specialized VFSes -** that do require it. +** No longer in use. +** +**
  • [[SQLITE_FCNTL_SYNC]] +** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and +** sent to the VFS immediately before the xSync method is invoked on a +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** of the xSync method. In most cases, the pointer argument passed with +** this file-control is NULL. However, if the database file is being synced +** as part of a multi-database commit, the argument points to a nul-terminated +** string containing the transactions master-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] +** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite +** and sent to the VFS after a transaction has been committed immediately +** but before the database is unlocked. VFSes that do not need this signal +** should silently ignore this opcode. Applications should not call +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. ** **
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic @@ -949,6 +1052,12 @@ struct sqlite3_io_methods { ** SQLite stack may generate instances of this file control if ** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. ** +**
  • [[SQLITE_FCNTL_HAS_MOVED]] +** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a +** pointer to an integer and it writes a boolean into that integer depending +** on whether or not the file has been renamed, moved, or deleted since it +** was first opened. +** ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -969,6 +1078,9 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_TEMPFILENAME 16 #define SQLITE_FCNTL_MMAP_SIZE 18 #define SQLITE_FCNTL_TRACE 19 +#define SQLITE_FCNTL_HAS_MOVED 20 +#define SQLITE_FCNTL_SYNC 21 +#define SQLITE_FCNTL_COMMIT_PHASETWO 22 /* ** CAPI3REF: Mutex Handle @@ -2403,11 +2515,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. +** ^If N is less than one, then P can be a NULL pointer. ** -** ^The first time this routine is invoked (either internally or by -** the application) the PRNG is seeded using randomness obtained -** from the xRandomness method of the default [sqlite3_vfs] object. -** ^On all subsequent invocations, the pseudo-randomness is generated +** ^If this routine has not been previously called or if the previous +** call had N less than one, then the PRNG is seeded using randomness +** obtained from the xRandomness method of the default [sqlite3_vfs] object. +** ^If the previous call to this routine had an N of 1 or more then +** the pseudo-randomness is generated ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ @@ -2567,6 +2681,7 @@ SQLITE_API int sqlite3_set_authorizer( #define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ +#define SQLITE_RECURSIVE 33 /* NULL NULL */ /* ** CAPI3REF: Tracing And Profiling Functions @@ -3985,15 +4100,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); ** ** ^The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Every SQL function implementation must be able to work -** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. ^An application may -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. +** its parameters. The application should set this parameter to +** [SQLITE_UTF16LE] if the function implementation invokes +** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the +** implementation invokes [sqlite3_value_text16be()] on an input, or +** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] +** otherwise. ^The same SQL function may be registered multiple times using +** different preferred text encodings, with different implementations for +** each encoding. ** ^When multiple implementations of the same function are available, SQLite ** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what text -** encoding is used, then the fourth argument should be [SQLITE_ANY]. +** +** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC] +** to signal that the function will always return the same result given +** the same inputs within a single SQL statement. Most SQL functions are +** deterministic. The built-in [random()] SQL function is an example of a +** function that is not deterministic. The SQLite query planner is able to +** perform additional optimizations on deterministic functions, so use +** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ @@ -4079,9 +4203,19 @@ SQLITE_API int sqlite3_create_function_v2( #define SQLITE_UTF16LE 2 #define SQLITE_UTF16BE 3 #define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ +/* +** CAPI3REF: Function Flags +** +** These constants may be ORed together with the +** [SQLITE_UTF8 | preferred text encoding] as the fourth argument +** to [sqlite3_create_function()], [sqlite3_create_function16()], or +** [sqlite3_create_function_v2()]. +*/ +#define SQLITE_DETERMINISTIC 0x800 + /* ** CAPI3REF: Deprecated Functions ** DEPRECATED @@ -6103,7 +6237,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 -#define SQLITE_TESTCTRL_LAST 20 +#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 +#define SQLITE_TESTCTRL_LAST 21 /* ** CAPI3REF: SQLite Runtime Status @@ -7366,50 +7501,7 @@ struct sqlite3_rtree_geometry { /************** End of sqlite3.h *********************************************/ -/************** Begin file sqliteInt.h ***************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Internal interface definitions for SQLite. -** -*/ -#ifndef _SQLITEINT_H_ -#define _SQLITEINT_H_ - -/* -** These #defines should enable >2GB file support on POSIX if the -** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. -** -** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any -** system #includes. Hence, this block of code must be the very first -** code in all source files. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: Red Hat 7.2) but you want your code to work -** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in Red Hat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 -#endif +/************** Continuing where we left off in sqliteInt.h ******************/ /* ** Include the configuration header output by 'configure' if we're using the @@ -7996,163 +8088,165 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include parse.h in the middle of sqliteInt.h *****************/ /************** Begin file parse.h *******************************************/ -#define TK_SEMI 1 -#define TK_EXPLAIN 2 -#define TK_QUERY 3 -#define TK_PLAN 4 -#define TK_BEGIN 5 -#define TK_TRANSACTION 6 -#define TK_DEFERRED 7 -#define TK_IMMEDIATE 8 -#define TK_EXCLUSIVE 9 -#define TK_COMMIT 10 -#define TK_END 11 -#define TK_ROLLBACK 12 -#define TK_SAVEPOINT 13 -#define TK_RELEASE 14 -#define TK_TO 15 -#define TK_TABLE 16 -#define TK_CREATE 17 -#define TK_IF 18 -#define TK_NOT 19 -#define TK_EXISTS 20 -#define TK_TEMP 21 -#define TK_LP 22 -#define TK_RP 23 -#define TK_AS 24 -#define TK_WITHOUT 25 -#define TK_COMMA 26 -#define TK_ID 27 -#define TK_INDEXED 28 -#define TK_ABORT 29 -#define TK_ACTION 30 -#define TK_AFTER 31 -#define TK_ANALYZE 32 -#define TK_ASC 33 -#define TK_ATTACH 34 -#define TK_BEFORE 35 -#define TK_BY 36 -#define TK_CASCADE 37 -#define TK_CAST 38 -#define TK_COLUMNKW 39 -#define TK_CONFLICT 40 -#define TK_DATABASE 41 -#define TK_DESC 42 -#define TK_DETACH 43 -#define TK_EACH 44 -#define TK_FAIL 45 -#define TK_FOR 46 -#define TK_IGNORE 47 -#define TK_INITIALLY 48 -#define TK_INSTEAD 49 -#define TK_LIKE_KW 50 -#define TK_MATCH 51 -#define TK_NO 52 -#define TK_KEY 53 -#define TK_OF 54 -#define TK_OFFSET 55 -#define TK_PRAGMA 56 -#define TK_RAISE 57 -#define TK_REPLACE 58 -#define TK_RESTRICT 59 -#define TK_ROW 60 -#define TK_TRIGGER 61 -#define TK_VACUUM 62 -#define TK_VIEW 63 -#define TK_VIRTUAL 64 -#define TK_REINDEX 65 -#define TK_RENAME 66 -#define TK_CTIME_KW 67 -#define TK_ANY 68 -#define TK_OR 69 -#define TK_AND 70 -#define TK_IS 71 -#define TK_BETWEEN 72 -#define TK_IN 73 -#define TK_ISNULL 74 -#define TK_NOTNULL 75 -#define TK_NE 76 -#define TK_EQ 77 -#define TK_GT 78 -#define TK_LE 79 -#define TK_LT 80 -#define TK_GE 81 -#define TK_ESCAPE 82 -#define TK_BITAND 83 -#define TK_BITOR 84 -#define TK_LSHIFT 85 -#define TK_RSHIFT 86 -#define TK_PLUS 87 -#define TK_MINUS 88 -#define TK_STAR 89 -#define TK_SLASH 90 -#define TK_REM 91 -#define TK_CONCAT 92 -#define TK_COLLATE 93 -#define TK_BITNOT 94 -#define TK_STRING 95 -#define TK_JOIN_KW 96 -#define TK_CONSTRAINT 97 -#define TK_DEFAULT 98 -#define TK_NULL 99 -#define TK_PRIMARY 100 -#define TK_UNIQUE 101 -#define TK_CHECK 102 -#define TK_REFERENCES 103 -#define TK_AUTOINCR 104 -#define TK_ON 105 -#define TK_INSERT 106 -#define TK_DELETE 107 -#define TK_UPDATE 108 -#define TK_SET 109 -#define TK_DEFERRABLE 110 -#define TK_FOREIGN 111 -#define TK_DROP 112 -#define TK_UNION 113 -#define TK_ALL 114 -#define TK_EXCEPT 115 -#define TK_INTERSECT 116 -#define TK_SELECT 117 -#define TK_DISTINCT 118 -#define TK_DOT 119 -#define TK_FROM 120 -#define TK_JOIN 121 -#define TK_USING 122 -#define TK_ORDER 123 -#define TK_GROUP 124 -#define TK_HAVING 125 -#define TK_LIMIT 126 -#define TK_WHERE 127 -#define TK_INTO 128 -#define TK_VALUES 129 -#define TK_INTEGER 130 -#define TK_FLOAT 131 -#define TK_BLOB 132 -#define TK_REGISTER 133 -#define TK_VARIABLE 134 -#define TK_CASE 135 -#define TK_WHEN 136 -#define TK_THEN 137 -#define TK_ELSE 138 -#define TK_INDEX 139 -#define TK_ALTER 140 -#define TK_ADD 141 -#define TK_TO_TEXT 142 -#define TK_TO_BLOB 143 -#define TK_TO_NUMERIC 144 -#define TK_TO_INT 145 -#define TK_TO_REAL 146 -#define TK_ISNOT 147 -#define TK_END_OF_FILE 148 -#define TK_ILLEGAL 149 -#define TK_SPACE 150 -#define TK_UNCLOSED_STRING 151 -#define TK_FUNCTION 152 -#define TK_COLUMN 153 -#define TK_AGG_FUNCTION 154 -#define TK_AGG_COLUMN 155 -#define TK_UMINUS 156 -#define TK_UPLUS 157 +#define TK_SEMI 1 +#define TK_EXPLAIN 2 +#define TK_QUERY 3 +#define TK_PLAN 4 +#define TK_BEGIN 5 +#define TK_TRANSACTION 6 +#define TK_DEFERRED 7 +#define TK_IMMEDIATE 8 +#define TK_EXCLUSIVE 9 +#define TK_COMMIT 10 +#define TK_END 11 +#define TK_ROLLBACK 12 +#define TK_SAVEPOINT 13 +#define TK_RELEASE 14 +#define TK_TO 15 +#define TK_TABLE 16 +#define TK_CREATE 17 +#define TK_IF 18 +#define TK_NOT 19 +#define TK_EXISTS 20 +#define TK_TEMP 21 +#define TK_LP 22 +#define TK_RP 23 +#define TK_AS 24 +#define TK_WITHOUT 25 +#define TK_COMMA 26 +#define TK_ID 27 +#define TK_INDEXED 28 +#define TK_ABORT 29 +#define TK_ACTION 30 +#define TK_AFTER 31 +#define TK_ANALYZE 32 +#define TK_ASC 33 +#define TK_ATTACH 34 +#define TK_BEFORE 35 +#define TK_BY 36 +#define TK_CASCADE 37 +#define TK_CAST 38 +#define TK_COLUMNKW 39 +#define TK_CONFLICT 40 +#define TK_DATABASE 41 +#define TK_DESC 42 +#define TK_DETACH 43 +#define TK_EACH 44 +#define TK_FAIL 45 +#define TK_FOR 46 +#define TK_IGNORE 47 +#define TK_INITIALLY 48 +#define TK_INSTEAD 49 +#define TK_LIKE_KW 50 +#define TK_MATCH 51 +#define TK_NO 52 +#define TK_KEY 53 +#define TK_OF 54 +#define TK_OFFSET 55 +#define TK_PRAGMA 56 +#define TK_RAISE 57 +#define TK_RECURSIVE 58 +#define TK_REPLACE 59 +#define TK_RESTRICT 60 +#define TK_ROW 61 +#define TK_TRIGGER 62 +#define TK_VACUUM 63 +#define TK_VIEW 64 +#define TK_VIRTUAL 65 +#define TK_WITH 66 +#define TK_REINDEX 67 +#define TK_RENAME 68 +#define TK_CTIME_KW 69 +#define TK_ANY 70 +#define TK_OR 71 +#define TK_AND 72 +#define TK_IS 73 +#define TK_BETWEEN 74 +#define TK_IN 75 +#define TK_ISNULL 76 +#define TK_NOTNULL 77 +#define TK_NE 78 +#define TK_EQ 79 +#define TK_GT 80 +#define TK_LE 81 +#define TK_LT 82 +#define TK_GE 83 +#define TK_ESCAPE 84 +#define TK_BITAND 85 +#define TK_BITOR 86 +#define TK_LSHIFT 87 +#define TK_RSHIFT 88 +#define TK_PLUS 89 +#define TK_MINUS 90 +#define TK_STAR 91 +#define TK_SLASH 92 +#define TK_REM 93 +#define TK_CONCAT 94 +#define TK_COLLATE 95 +#define TK_BITNOT 96 +#define TK_STRING 97 +#define TK_JOIN_KW 98 +#define TK_CONSTRAINT 99 +#define TK_DEFAULT 100 +#define TK_NULL 101 +#define TK_PRIMARY 102 +#define TK_UNIQUE 103 +#define TK_CHECK 104 +#define TK_REFERENCES 105 +#define TK_AUTOINCR 106 +#define TK_ON 107 +#define TK_INSERT 108 +#define TK_DELETE 109 +#define TK_UPDATE 110 +#define TK_SET 111 +#define TK_DEFERRABLE 112 +#define TK_FOREIGN 113 +#define TK_DROP 114 +#define TK_UNION 115 +#define TK_ALL 116 +#define TK_EXCEPT 117 +#define TK_INTERSECT 118 +#define TK_SELECT 119 +#define TK_VALUES 120 +#define TK_DISTINCT 121 +#define TK_DOT 122 +#define TK_FROM 123 +#define TK_JOIN 124 +#define TK_USING 125 +#define TK_ORDER 126 +#define TK_GROUP 127 +#define TK_HAVING 128 +#define TK_LIMIT 129 +#define TK_WHERE 130 +#define TK_INTO 131 +#define TK_INTEGER 132 +#define TK_FLOAT 133 +#define TK_BLOB 134 +#define TK_VARIABLE 135 +#define TK_CASE 136 +#define TK_WHEN 137 +#define TK_THEN 138 +#define TK_ELSE 139 +#define TK_INDEX 140 +#define TK_ALTER 141 +#define TK_ADD 142 +#define TK_TO_TEXT 143 +#define TK_TO_BLOB 144 +#define TK_TO_NUMERIC 145 +#define TK_TO_INT 146 +#define TK_TO_REAL 147 +#define TK_ISNOT 148 +#define TK_END_OF_FILE 149 +#define TK_ILLEGAL 150 +#define TK_SPACE 151 +#define TK_UNCLOSED_STRING 152 +#define TK_FUNCTION 153 +#define TK_COLUMN 154 +#define TK_AGG_FUNCTION 155 +#define TK_AGG_COLUMN 156 +#define TK_UMINUS 157 +#define TK_UPLUS 158 +#define TK_REGISTER 159 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -8583,6 +8677,7 @@ typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; +typedef struct PrintfArguments PrintfArguments; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; @@ -8600,6 +8695,7 @@ typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; +typedef struct With With; /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and @@ -8792,8 +8888,6 @@ SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); -SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); @@ -8933,9 +9027,12 @@ struct VdbeOp { char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE - int cnt; /* Number of times this instruction was executed */ + u32 cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif +#ifdef SQLITE_VDBE_COVERAGE + int iSrcLine; /* Source-code line that generated this opcode */ +#endif }; typedef struct VdbeOp VdbeOp; @@ -9045,139 +9142,143 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Gosub 17 #define OP_Return 18 #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_Yield 20 -#define OP_HaltIfNull 21 /* synopsis: if r[P3] null then halt */ -#define OP_Halt 22 -#define OP_Integer 23 /* synopsis: r[P2]=P1 */ -#define OP_Int64 24 /* synopsis: r[P2]=P4 */ -#define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 26 /* synopsis: r[P2..P3]=NULL */ -#define OP_Blob 27 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 28 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 29 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 30 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_SCopy 31 /* synopsis: r[P2]=r[P1] */ -#define OP_ResultRow 32 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 33 -#define OP_AddImm 34 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_MustBeInt 35 -#define OP_RealAffinity 36 -#define OP_Permutation 37 -#define OP_Compare 38 -#define OP_Jump 39 -#define OP_Once 40 -#define OP_If 41 -#define OP_IfNot 42 -#define OP_Column 43 /* synopsis: r[P3]=PX */ -#define OP_Affinity 44 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 45 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 46 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 47 -#define OP_SetCookie 48 -#define OP_VerifyCookie 49 -#define OP_OpenRead 50 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 51 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenAutoindex 52 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 53 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 54 -#define OP_OpenPseudo 55 /* synopsis: content in r[P2@P3] */ -#define OP_Close 56 -#define OP_SeekLt 57 /* synopsis: key=r[P3@P4] */ -#define OP_SeekLe 58 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGe 59 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGt 60 /* synopsis: key=r[P3@P4] */ -#define OP_Seek 61 /* synopsis: intkey=r[P2] */ -#define OP_NoConflict 62 /* synopsis: key=r[P3@P4] */ -#define OP_NotFound 63 /* synopsis: key=r[P3@P4] */ -#define OP_Found 64 /* synopsis: key=r[P3@P4] */ -#define OP_NotExists 65 /* synopsis: intkey=r[P3] */ -#define OP_Sequence 66 /* synopsis: r[P2]=rowid */ -#define OP_NewRowid 67 /* synopsis: r[P2]=rowid */ -#define OP_Insert 68 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_Or 69 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ -#define OP_And 70 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_InsertInt 71 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_Delete 72 -#define OP_ResetCount 73 -#define OP_IsNull 74 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ -#define OP_NotNull 75 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 76 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ -#define OP_Eq 77 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ -#define OP_Gt 78 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ -#define OP_Le 79 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ -#define OP_Lt 80 /* same as TK_LT, synopsis: if r[P1]=r[P3] goto P2 */ -#define OP_SorterCompare 82 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */ -#define OP_BitAnd 83 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 84 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 85 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 87 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 88 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 89 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 90 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 91 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 92 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_SorterData 93 /* synopsis: r[P2]=data */ -#define OP_BitNot 94 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ -#define OP_String8 95 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_RowKey 96 /* synopsis: r[P2]=key */ -#define OP_RowData 97 /* synopsis: r[P2]=data */ -#define OP_Rowid 98 /* synopsis: r[P2]=rowid */ -#define OP_NullRow 99 -#define OP_Last 100 -#define OP_SorterSort 101 -#define OP_Sort 102 -#define OP_Rewind 103 -#define OP_SorterInsert 104 -#define OP_IdxInsert 105 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 106 /* synopsis: key=r[P2@P3] */ -#define OP_IdxRowid 107 /* synopsis: r[P2]=rowid */ -#define OP_IdxLT 108 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGE 109 /* synopsis: key=r[P3@P4] */ -#define OP_Destroy 110 -#define OP_Clear 111 -#define OP_CreateIndex 112 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_CreateTable 113 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_ParseSchema 114 -#define OP_LoadAnalysis 115 -#define OP_DropTable 116 -#define OP_DropIndex 117 -#define OP_DropTrigger 118 -#define OP_IntegrityCk 119 -#define OP_RowSetAdd 120 /* synopsis: rowset(P1)=r[P2] */ -#define OP_RowSetRead 121 /* synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 122 /* synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 123 -#define OP_Param 124 -#define OP_FkCounter 125 /* synopsis: fkctr[P1]+=P2 */ -#define OP_FkIfZero 126 /* synopsis: if fkctr[P1]==0 goto P2 */ -#define OP_MemMax 127 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_IfPos 128 /* synopsis: if r[P1]>0 goto P2 */ -#define OP_IfNeg 129 /* synopsis: if r[P1]<0 goto P2 */ -#define OP_IfZero 130 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */ -#define OP_Real 131 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_AggFinal 132 /* synopsis: accum=r[P1] N=P2 */ -#define OP_IncrVacuum 133 -#define OP_Expire 134 -#define OP_TableLock 135 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 136 -#define OP_VCreate 137 -#define OP_VDestroy 138 -#define OP_VOpen 139 -#define OP_VColumn 140 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VNext 141 -#define OP_ToText 142 /* same as TK_TO_TEXT */ -#define OP_ToBlob 143 /* same as TK_TO_BLOB */ -#define OP_ToNumeric 144 /* same as TK_TO_NUMERIC */ -#define OP_ToInt 145 /* same as TK_TO_INT */ -#define OP_ToReal 146 /* same as TK_TO_REAL */ -#define OP_VRename 147 -#define OP_Pagecount 148 -#define OP_MaxPgcnt 149 -#define OP_Trace 150 -#define OP_Noop 151 -#define OP_Explain 152 +#define OP_InitCoroutine 20 +#define OP_EndCoroutine 21 +#define OP_Yield 22 +#define OP_HaltIfNull 23 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 24 +#define OP_Integer 25 /* synopsis: r[P2]=P1 */ +#define OP_Int64 26 /* synopsis: r[P2]=P4 */ +#define OP_String 27 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 28 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 29 /* synopsis: r[P1]=NULL */ +#define OP_Blob 30 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 31 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 32 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 33 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 34 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 35 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 36 +#define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_MustBeInt 38 +#define OP_RealAffinity 39 +#define OP_Permutation 40 +#define OP_Compare 41 +#define OP_Jump 42 +#define OP_Once 43 +#define OP_If 44 +#define OP_IfNot 45 +#define OP_Column 46 /* synopsis: r[P3]=PX */ +#define OP_Affinity 47 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 48 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 49 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 50 +#define OP_SetCookie 51 +#define OP_OpenRead 52 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 53 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenAutoindex 54 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 55 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 56 +#define OP_OpenPseudo 57 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 58 +#define OP_SeekLT 59 +#define OP_SeekLE 60 +#define OP_SeekGE 61 +#define OP_SeekGT 62 +#define OP_Seek 63 /* synopsis: intkey=r[P2] */ +#define OP_NoConflict 64 /* synopsis: key=r[P3@P4] */ +#define OP_NotFound 65 /* synopsis: key=r[P3@P4] */ +#define OP_Found 66 /* synopsis: key=r[P3@P4] */ +#define OP_NotExists 67 /* synopsis: intkey=r[P3] */ +#define OP_Sequence 68 /* synopsis: r[P2]=rowid */ +#define OP_NewRowid 69 /* synopsis: r[P2]=rowid */ +#define OP_Insert 70 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ +#define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ +#define OP_InsertInt 73 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 74 +#define OP_ResetCount 75 +#define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ +#define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ +#define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ +#define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ +#define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ +#define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ +#define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]=r[P3] goto P2 */ +#define OP_SorterCompare 84 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */ +#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ +#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ +#define OP_SorterData 95 /* synopsis: r[P2]=data */ +#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ +#define OP_RowKey 98 /* synopsis: r[P2]=key */ +#define OP_RowData 99 /* synopsis: r[P2]=data */ +#define OP_Rowid 100 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 101 +#define OP_Last 102 +#define OP_SorterSort 103 +#define OP_Sort 104 +#define OP_Rewind 105 +#define OP_SorterInsert 106 +#define OP_IdxInsert 107 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 108 /* synopsis: key=r[P2@P3] */ +#define OP_IdxRowid 109 /* synopsis: r[P2]=rowid */ +#define OP_IdxLE 110 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGT 111 /* synopsis: key=r[P3@P4] */ +#define OP_IdxLT 112 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGE 113 /* synopsis: key=r[P3@P4] */ +#define OP_Destroy 114 +#define OP_Clear 115 +#define OP_CreateIndex 116 /* synopsis: r[P2]=root iDb=P1 */ +#define OP_CreateTable 117 /* synopsis: r[P2]=root iDb=P1 */ +#define OP_ParseSchema 118 +#define OP_LoadAnalysis 119 +#define OP_DropTable 120 +#define OP_DropIndex 121 +#define OP_DropTrigger 122 +#define OP_IntegrityCk 123 +#define OP_RowSetAdd 124 /* synopsis: rowset(P1)=r[P2] */ +#define OP_RowSetRead 125 /* synopsis: r[P3]=rowset(P1) */ +#define OP_RowSetTest 126 /* synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 127 +#define OP_Param 128 +#define OP_FkCounter 129 /* synopsis: fkctr[P1]+=P2 */ +#define OP_FkIfZero 130 /* synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_MemMax 131 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_IfPos 132 /* synopsis: if r[P1]>0 goto P2 */ +#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#define OP_IfNeg 134 /* synopsis: if r[P1]<0 goto P2 */ +#define OP_IfZero 135 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */ +#define OP_AggFinal 136 /* synopsis: accum=r[P1] N=P2 */ +#define OP_IncrVacuum 137 +#define OP_Expire 138 +#define OP_TableLock 139 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 140 +#define OP_VCreate 141 +#define OP_VDestroy 142 +#define OP_ToText 143 /* same as TK_TO_TEXT */ +#define OP_ToBlob 144 /* same as TK_TO_BLOB */ +#define OP_ToNumeric 145 /* same as TK_TO_NUMERIC */ +#define OP_ToInt 146 /* same as TK_TO_INT */ +#define OP_ToReal 147 /* same as TK_TO_REAL */ +#define OP_VOpen 148 +#define OP_VColumn 149 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VNext 150 +#define OP_VRename 151 +#define OP_Pagecount 152 +#define OP_MaxPgcnt 153 +#define OP_Init 154 /* synopsis: Start at P2 */ +#define OP_Noop 155 +#define OP_Explain 156 /* Properties such as "out2" or "jump" that are specified in @@ -9194,24 +9295,24 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\ /* 8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\ -/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x04, 0x10, 0x00, 0x02,\ -/* 24 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x20,\ -/* 32 */ 0x00, 0x00, 0x04, 0x05, 0x04, 0x00, 0x00, 0x01,\ -/* 40 */ 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x02,\ -/* 48 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 56 */ 0x00, 0x11, 0x11, 0x11, 0x11, 0x08, 0x11, 0x11,\ -/* 64 */ 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c, 0x4c, 0x00,\ -/* 72 */ 0x00, 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15,\ -/* 80 */ 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\ -/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x24, 0x02,\ -/* 96 */ 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,\ -/* 104 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\ -/* 112 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 120 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\ -/* 128 */ 0x05, 0x05, 0x05, 0x02, 0x00, 0x01, 0x00, 0x00,\ -/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x04,\ -/* 144 */ 0x04, 0x04, 0x04, 0x00, 0x02, 0x02, 0x00, 0x00,\ -/* 152 */ 0x00,} +/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\ +/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\ +/* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\ +/* 40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\ +/* 48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\ +/* 64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\ +/* 72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\ +/* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\ +/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\ +/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\ +/* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\ +/* 112 */ 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01,\ +/* 128 */ 0x02, 0x00, 0x01, 0x08, 0x05, 0x02, 0x05, 0x05,\ +/* 136 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,\ +/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x01, 0x00,\ +/* 152 */ 0x02, 0x02, 0x01, 0x00, 0x00,} /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -9220,14 +9321,14 @@ typedef struct VdbeOpList VdbeOpList; ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ -SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*); +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*); SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); -SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); @@ -9235,6 +9336,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr); +SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); @@ -9267,9 +9369,12 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); -SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int); SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); +typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int); +SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); + #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif @@ -9297,6 +9402,43 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); # define VdbeModuleComment(X) #endif +/* +** The VdbeCoverage macros are used to set a coverage testing point +** for VDBE branch instructions. The coverage testing points are line +** numbers in the sqlite3.c source file. VDBE branch coverage testing +** only works with an amalagmation build. That's ok since a VDBE branch +** coverage build designed for testing the test suite only. No application +** should ever ship with VDBE branch coverage measuring turned on. +** +** VdbeCoverage(v) // Mark the previously coded instruction +** // as a branch +** +** VdbeCoverageIf(v, conditional) // Mark previous if conditional true +** +** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken +** +** VdbeCoverageNeverTaken(v) // Previous branch is never taken +** +** Every VDBE branch operation must be tagged with one of the macros above. +** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and +** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() +** routine in vdbe.c, alerting the developer to the missed tag. +*/ +#ifdef SQLITE_VDBE_COVERAGE +SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); +# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); +# define VDBE_OFFSET_LINENO(x) (__LINE__+x) +#else +# define VdbeCoverage(v) +# define VdbeCoverageIf(v,x) +# define VdbeCoverageAlwaysTaken(v) +# define VdbeCoverageNeverTaken(v) +# define VDBE_OFFSET_LINENO(x) 0 +#endif + #endif /************** End of vdbe.h ************************************************/ @@ -9441,6 +9583,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); /* Operations on page references. */ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); @@ -9455,7 +9598,7 @@ SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster); SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); @@ -10327,7 +10470,7 @@ struct sqlite3 { #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ -#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ +/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ @@ -10353,8 +10496,7 @@ struct sqlite3 { ** Return true if it OK to factor constant expressions into the initialization ** code. The argument is a Parse object for the code generator. */ -#define ConstFactorOk(P) \ - ((P)->cookieGoto>0 && OptimizationEnabled((P)->db,SQLITE_FactorOutConst)) +#define ConstFactorOk(P) ((P)->okConstFactor) /* ** Possible values for the sqlite.magic field. @@ -10580,10 +10722,16 @@ struct CollSeq { /* ** Additional bit values that can be ORed with an affinity without ** changing the affinity. +** +** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. +** It causes an assert() to fire if either operand to a comparison +** operator is NULL. It is added to certain comparison operators to +** prove that the operands are always NOT NULL. */ #define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ +#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */ /* ** An object of this type is created for each virtual table present in @@ -10699,7 +10847,7 @@ struct Table { }; /* -** Allowed values for Tabe.tabFlags. +** Allowed values for Table.tabFlags. */ #define TF_Readonly 0x01 /* Read-only system table */ #define TF_Ephemeral 0x02 /* An ephemeral table */ @@ -10842,19 +10990,19 @@ struct KeyInfo { ** ** This structure holds a record that has already been disassembled ** into its constituent fields. +** +** The r1 and r2 member variables are only used by the optimized comparison +** functions vdbeRecordCompareInt() and vdbeRecordCompareString(). */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ - u8 flags; /* Boolean settings. UNPACKED_... below */ + i8 default_rc; /* Comparison result if keys are equal */ Mem *aMem; /* Values */ + int r1; /* Value to return if (lhs > rhs) */ + int r2; /* Value to return if (rhs < lhs) */ }; -/* -** Allowed values of UnpackedRecord.flags -*/ -#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */ -#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */ /* ** Each SQL index is represented in memory by an @@ -10959,6 +11107,7 @@ struct AggInfo { int sortingIdx; /* Cursor number of the sorting index */ int sortingIdxPTab; /* Cursor number of pseudo-table */ int nSortingColumn; /* Number of columns in the sorting index */ + int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */ ExprList *pGroupBy; /* The group by clause */ struct AggInfo_col { /* For each column used in source tables */ Table *pTab; /* Source table */ @@ -11251,6 +11400,7 @@ typedef u64 Bitmask; ** A bit in a Bitmask */ #define MASKBIT(n) (((Bitmask)1)<<(n)) +#define MASKBIT32(n) (((unsigned int)1)<<(n)) /* ** The following structure describes the FROM clause of a SELECT statement. @@ -11272,8 +11422,8 @@ typedef u64 Bitmask; ** contains more than 63 columns and the 64-th or later column is used. */ struct SrcList { - u8 nSrc; /* Number of tables or subqueries in the FROM clause */ - u8 nAlloc; /* Number of entries allocated in a[] below */ + int nSrc; /* Number of tables or subqueries in the FROM clause */ + u32 nAlloc; /* Number of entries allocated in a[] below */ struct SrcList_item { Schema *pSchema; /* Schema to which this item is fixed */ char *zDatabase; /* Name of database holding this table */ @@ -11283,10 +11433,12 @@ struct SrcList { Select *pSelect; /* A SELECT statement used in place of a table name */ int addrFillSub; /* Address of subroutine to manifest a subquery */ int regReturn; /* Register holding return address of addrFillSub */ + int regResult; /* Registers holding results of a co-routine */ u8 jointype; /* Type of join between this able and the previous */ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ unsigned isCorrelated :1; /* True if sub-query is correlated */ unsigned viaCoroutine :1; /* Implemented as a co-routine */ + unsigned isRecursive :1; /* True for recursive reference in WITH */ #ifndef SQLITE_OMIT_EXPLAIN u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ #endif @@ -11410,9 +11562,9 @@ struct Select { ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ Select *pNext; /* Next select to the left in a compound */ - Select *pRightmost; /* Right-most select in a compound select statement */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ Expr *pOffset; /* OFFSET expression. NULL means not used. */ + With *pWith; /* WITH clause attached to this select. Or NULL. */ }; /* @@ -11427,14 +11579,74 @@ struct Select { #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x0040 /* Sort using a sorter */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ -#define SF_Materialize 0x0100 /* Force materialization of views */ +#define SF_Materialize 0x0100 /* NOT USED */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ #define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */ +#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */ +#define SF_Compound 0x1000 /* Part of a compound query */ /* -** The results of a select can be distributed in several ways. The -** "SRT" prefix means "SELECT Result Type". +** The results of a SELECT can be distributed in several ways, as defined +** by one of the following macros. The "SRT" prefix means "SELECT Result +** Type". +** +** SRT_Union Store results as a key in a temporary index +** identified by pDest->iSDParm. +** +** SRT_Except Remove results from the temporary index pDest->iSDParm. +** +** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result +** set is not empty. +** +** SRT_Discard Throw the results away. This is used by SELECT +** statements within triggers whose only purpose is +** the side-effects of functions. +** +** All of the above are free to ignore their ORDER BY clause. Those that +** follow must honor the ORDER BY clause. +** +** SRT_Output Generate a row of output (using the OP_ResultRow +** opcode) for each row in the result set. +** +** SRT_Mem Only valid if the result is a single column. +** Store the first column of the first result row +** in register pDest->iSDParm then abandon the rest +** of the query. This destination implies "LIMIT 1". +** +** SRT_Set The result must be a single column. Store each +** row of result as the key in table pDest->iSDParm. +** Apply the affinity pDest->affSdst before storing +** results. Used to implement "IN (SELECT ...)". +** +** SRT_EphemTab Create an temporary table pDest->iSDParm and store +** the result there. The cursor is left open after +** returning. This is like SRT_Table except that +** this destination uses OP_OpenEphemeral to create +** the table first. +** +** SRT_Coroutine Generate a co-routine that returns a new row of +** results each time it is invoked. The entry point +** of the co-routine is stored in register pDest->iSDParm +** and the result row is stored in pDest->nDest registers +** starting with pDest->iSdst. +** +** SRT_Table Store results in temporary table pDest->iSDParm. +** This is like SRT_EphemTab except that the table +** is assumed to already be open. +** +** SRT_DistTable Store results in a temporary table pDest->iSDParm. +** But also use temporary table pDest->iSDParm+1 as +** a record of all prior results and ignore any duplicate +** rows. Name means: "Distinct Table". +** +** SRT_Queue Store results in priority queue pDest->iSDParm (really +** an index). Append a sequence number so that all entries +** are distinct. +** +** SRT_DistQueue Store results in priority queue pDest->iSDParm only if +** the same record has never been stored before. The +** index at pDest->iSDParm+1 hold all prior stores. */ #define SRT_Union 1 /* Store result as keys in an index */ #define SRT_Except 2 /* Remove result from a UNION index */ @@ -11447,20 +11659,24 @@ struct Select { #define SRT_Output 5 /* Output each row of result */ #define SRT_Mem 6 /* Store result in a memory cell */ #define SRT_Set 7 /* Store results as keys in an index */ -#define SRT_Table 8 /* Store result as data with an automatic rowid */ -#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */ -#define SRT_Coroutine 10 /* Generate a single row of result */ +#define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */ +#define SRT_Coroutine 9 /* Generate a single row of result */ +#define SRT_Table 10 /* Store result as data with an automatic rowid */ +#define SRT_DistTable 11 /* Like SRT_Table, but unique results only */ +#define SRT_Queue 12 /* Store result in an queue */ +#define SRT_DistQueue 13 /* Like SRT_Queue, but unique results only */ /* ** An instance of this object describes where to put of the results of ** a SELECT statement. */ struct SelectDest { - u8 eDest; /* How to dispose of the results. On of SRT_* above. */ - char affSdst; /* Affinity used when eDest==SRT_Set */ - int iSDParm; /* A parameter used by the eDest disposal method */ - int iSdst; /* Base register where results are written */ - int nSdst; /* Number of registers allocated */ + u8 eDest; /* How to dispose of the results. On of SRT_* above. */ + char affSdst; /* Affinity used when eDest==SRT_Set */ + int iSDParm; /* A parameter used by the eDest disposal method */ + int iSdst; /* Base register where results are written */ + int nSdst; /* Number of registers allocated */ + ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ }; /* @@ -11546,12 +11762,12 @@ struct Parse { u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ - u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ + u8 okConstFactor; /* OK to factor out constants */ int aTempReg[8]; /* Holding area for temporary registers */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ @@ -11560,27 +11776,30 @@ struct Parse { int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nOnce; /* Number of OP_Once instructions so far */ + int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ + int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ int ckBase; /* Base register of data during check constraints */ int iPartIdxTab; /* Table corresponding to a partial index */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ + int nLabel; /* Number of labels used */ + int *aLabel; /* Space to hold the labels */ struct yColCache { int iTable; /* Table cursor number */ - int iColumn; /* Table column number */ + i16 iColumn; /* Table column number */ u8 tempReg; /* iReg is a temp register that needs to be freed */ int iLevel; /* Nesting level */ int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ ExprList *pConstExpr;/* Constant expressions */ + Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ - int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ - Token constraintName;/* Name of the constraint currently being parsed */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ @@ -11599,12 +11818,17 @@ struct Parse { u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ - /* Above is constant between recursions. Below is reset before and after - ** each recursion */ + /************************************************************************ + ** Above is constant between recursions. Below is reset before and after + ** each recursion. The boundary between these two regions is determined + ** using offsetof(Parse,nVar) so the nVar field must be the first field + ** in the recursive region. + ************************************************************************/ int nVar; /* Number of '?' variables seen in the SQL so far */ int nzVar; /* Number of available slots in azVar[] */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ + u8 bFreeWith; /* True if pWith should be freed with parser */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ @@ -11630,6 +11854,7 @@ struct Parse { #endif Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ + With *pWith; /* Current WITH clause, or NULL */ }; /* @@ -11749,7 +11974,7 @@ struct TriggerStep { Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ Token target; /* Target table for DELETE, UPDATE, INSERT */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ - ExprList *pExprList; /* SET clause for UPDATE. VALUES clause for INSERT */ + ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ TriggerStep *pNext; /* Next in the link-list */ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ @@ -11845,6 +12070,13 @@ struct Sqlite3Config { void(*xSqllog)(void*,sqlite3*,const char*, int); void *pSqllogArg; #endif +#ifdef SQLITE_VDBE_COVERAGE + /* The following callback (if not NULL) is invoked on every VDBE branch + ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. + */ + void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ + void *pVdbeBranchArg; /* 1st argument */ +#endif }; /* @@ -11871,9 +12103,9 @@ struct Sqlite3Config { struct Walker { int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ + void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ Parse *pParse; /* Parser context. */ int walkerDepth; /* Number of subqueries */ - u8 bSelectDepthFirst; /* Do subqueries first */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ @@ -11897,6 +12129,21 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); #define WRC_Prune 1 /* Omit children but continue walking siblings */ #define WRC_Abort 2 /* Abandon the tree walk */ +/* +** An instance of this structure represents a set of one or more CTEs +** (common table expressions) created by a single WITH clause. +*/ +struct With { + int nCte; /* Number of CTEs in the WITH clause */ + With *pOuter; /* Containing WITH clause, or NULL */ + struct Cte { /* For each CTE in the WITH clause.... */ + char *zName; /* Name of this CTE */ + ExprList *pCols; /* List of explicit column names, or NULL */ + Select *pSelect; /* The definition of this CTE */ + const char *zErr; /* Error message for circular references */ + } a[1]; +}; + /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. @@ -12036,10 +12283,20 @@ SQLITE_PRIVATE int sqlite3IsNaN(double); # define sqlite3IsNaN(X) 0 #endif -SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); -#ifndef SQLITE_OMIT_TRACE -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); -#endif +/* +** An instance of the following structure holds information about SQL +** functions arguments that are the parameters to the printf() function. +*/ +struct PrintfArguments { + int nArg; /* Total number of arguments */ + int nUsed; /* Number of arguments used so far */ + sqlite3_value **apArg; /* The argument values */ +}; + +#define SQLITE_PRINTF_INTERNAL 0x01 +#define SQLITE_PRINTF_SQLFUNC 0x02 +SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list); +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...); SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...); @@ -12153,8 +12410,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif -SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*); -SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); +SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); @@ -12201,11 +12457,12 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int); SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); -SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ @@ -12229,7 +12486,6 @@ SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); -SQLITE_PRIVATE void sqlite3PrngResetState(void); SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); @@ -12244,12 +12500,11 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*); SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); -SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*); -SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*); +SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); @@ -12293,7 +12548,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, - ExprList*,Select*,u8); + Select*,u8); SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); @@ -12388,7 +12643,7 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v); SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *); -SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *); +SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); @@ -12398,8 +12653,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \ - defined(SQLITE_DEBUG_OS_TRACE) +#if defined(SQLITE_TEST) SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif @@ -12429,6 +12683,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); +SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*); SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*); SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *); SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); @@ -12494,6 +12749,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int); SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); +SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); @@ -12585,6 +12841,14 @@ SQLITE_PRIVATE const char *sqlite3JournalModename(int); SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif +#ifndef SQLITE_OMIT_CTE +SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); +SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); +SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8); +#else +#define sqlite3WithPush(x,y,z) +#define sqlite3WithDelete(x,y) +#endif /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign @@ -13192,6 +13456,9 @@ static const char * const azCompileOpt[] = { #ifdef SQLITE_OMIT_COMPOUND_SELECT "OMIT_COMPOUND_SELECT", #endif +#ifdef SQLITE_OMIT_CTE + "OMIT_CTE", +#endif #ifdef SQLITE_OMIT_DATETIME_FUNCS "OMIT_DATETIME_FUNCS", #endif @@ -13483,7 +13750,6 @@ struct VdbeCursor { Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ Bool isTable:1; /* True if a table requiring integer keys */ Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ - Bool multiPseudo:1; /* Multi-register pseudo-cursor */ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ @@ -13577,7 +13843,6 @@ struct Mem { } u; int n; /* Number of characters in string value, excluding '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ - u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ @@ -13604,9 +13869,10 @@ struct Mem { #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ +#define MEM_AffMask 0x001f /* Mask of affinity bits */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ -#define MEM_Invalid 0x0080 /* Value is undefined */ +#define MEM_Undefined 0x0080 /* Value is undefined */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ #define MEM_TypeMask 0x01ff /* Mask of type bits */ @@ -13617,7 +13883,7 @@ struct Mem { ** string is \000 or \u0000 terminated */ #define MEM_Term 0x0200 /* String rep is nul terminated */ -#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */ +#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ #define MEM_Static 0x0800 /* Mem.z points to a static string */ #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ @@ -13638,7 +13904,7 @@ struct Mem { ** is for use inside assert() statements only. */ #ifdef SQLITE_DEBUG -#define memIsValid(M) ((M)->flags & MEM_Invalid)==0 +#define memIsValid(M) ((M)->flags & MEM_Undefined)==0 #endif /* @@ -13720,12 +13986,9 @@ struct Vdbe { Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ Mem *pResultSet; /* Pointer to an array of results */ + Parse *pParse; /* Parsing context used to create this Vdbe */ int nMem; /* Number of memory locations currently allocated */ int nOp; /* Number of instructions in the program */ - int nOpAlloc; /* Number of slots allocated for aOp[] */ - int nLabel; /* Number of labels used */ - int *aLabel; /* Space to hold the labels */ - u16 nResColumn; /* Number of columns in one row of the result set */ int nCursor; /* Number of slots in apCsr[] */ u32 magic; /* Magic number for sanity checking */ char *zErrMsg; /* Error message written here */ @@ -13738,6 +14001,7 @@ struct Vdbe { u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ + u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ @@ -13797,12 +14061,12 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); #endif SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int); -SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int); +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); +SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*); SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *); SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); @@ -13835,16 +14099,16 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p); +#define VdbeMemDynamic(X) \ + (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) #define VdbeMemRelease(X) \ - if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \ - sqlite3VdbeMemReleaseExternal(X); + if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); SQLITE_PRIVATE const char *sqlite3OpcodeName(int); SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); -SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem); SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *); @@ -13865,6 +14129,7 @@ SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*); +SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*); #endif #ifndef SQLITE_OMIT_FOREIGN_KEY @@ -15391,7 +15656,21 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ ** routine has no return value since the return value would be meaningless. */ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ - DO_OS_MALLOC_TEST(id); +#ifdef SQLITE_TEST + if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ + /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite + ** is using a regular VFS, it is called after the corresponding + ** transaction has been committed. Injecting a fault at this point + ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM + ** but the transaction is committed anyway. + ** + ** The core must call OsFileControl() though, not OsFileControlHint(), + ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably + ** means the commit really has failed and an error should be returned + ** to the user. */ + DO_OS_MALLOC_TEST(id); + } +#endif return id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ @@ -17603,6 +17882,12 @@ static void *memsys5MallocUnsafe(int nByte){ if( mem5.maxCount=db->lookaside.pStart && plookaside.pEnd; + return p>=db->lookaside.pStart && plookaside.pEnd; } #else #define isLookaside(A,B) 0 @@ -19402,8 +19694,9 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){ return sqlite3GlobalConfig.m.xSize(p); } SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - if( db && isLookaside(db, p) ){ + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + if( isLookaside(db, p) ){ return db->lookaside.sz; }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); @@ -19886,6 +20179,31 @@ SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){ } } +/* +** Set the StrAccum object to an error mode. +*/ +static void setStrAccumError(StrAccum *p, u8 eError){ + p->accError = eError; + p->nAlloc = 0; +} + +/* +** Extra argument values from a PrintfArguments object +*/ +static sqlite3_int64 getIntArg(PrintfArguments *p){ + if( p->nArg<=p->nUsed ) return 0; + return sqlite3_value_int64(p->apArg[p->nUsed++]); +} +static double getDoubleArg(PrintfArguments *p){ + if( p->nArg<=p->nUsed ) return 0.0; + return sqlite3_value_double(p->apArg[p->nUsed++]); +} +static char *getTextArg(PrintfArguments *p){ + if( p->nArg<=p->nUsed ) return 0; + return (char*)sqlite3_value_text(p->apArg[p->nUsed++]); +} + + /* ** On machines with a small stack size, you can redefine the ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. @@ -19899,10 +20217,10 @@ SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){ ** Render a string given by "fmt" into the StrAccum object. */ SQLITE_PRIVATE void sqlite3VXPrintf( - StrAccum *pAccum, /* Accumulate results here */ - int useExtended, /* Allow extended %-conversions */ - const char *fmt, /* Format string */ - va_list ap /* arguments */ + StrAccum *pAccum, /* Accumulate results here */ + u32 bFlags, /* SQLITE_PRINTF_* flags */ + const char *fmt, /* Format string */ + va_list ap /* arguments */ ){ int c; /* Next character in the format string */ char *bufpt; /* Pointer to the conversion buffer */ @@ -19920,6 +20238,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf( etByte flag_longlong; /* True if the "ll" flag is present */ etByte done; /* Loop termination flag */ etByte xtype = 0; /* Conversion paradigm */ + u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ + u8 useIntern; /* Ok to use internal conversions (ex: %T) */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ @@ -19934,9 +20254,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf( etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ #endif + PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ bufpt = 0; + if( bFlags ){ + if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ + pArgList = va_arg(ap, PrintfArguments*); + } + useIntern = bFlags & SQLITE_PRINTF_INTERNAL; + }else{ + bArgList = useIntern = 0; + } for(; (c=(*fmt))!=0; ++fmt){ if( c!='%' ){ int amt; @@ -19968,7 +20297,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( /* Get the field width */ width = 0; if( c=='*' ){ - width = va_arg(ap,int); + if( bArgList ){ + width = (int)getIntArg(pArgList); + }else{ + width = va_arg(ap,int); + } if( width<0 ){ flag_leftjustify = 1; width = -width; @@ -19985,7 +20318,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( precision = 0; c = *++fmt; if( c=='*' ){ - precision = va_arg(ap,int); + if( bArgList ){ + precision = (int)getIntArg(pArgList); + }else{ + precision = va_arg(ap,int); + } if( precision<0 ) precision = -precision; c = *++fmt; }else{ @@ -20016,7 +20353,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( for(idx=0; idxflags & FLAG_INTERN)==0 ){ + if( useIntern || (infop->flags & FLAG_INTERN)==0 ){ xtype = infop->type; }else{ return; @@ -20056,7 +20393,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf( case etRADIX: if( infop->flags & FLAG_SIGNED ){ i64 v; - if( flag_longlong ){ + if( bArgList ){ + v = getIntArg(pArgList); + }else if( flag_longlong ){ v = va_arg(ap,i64); }else if( flag_long ){ v = va_arg(ap,long int); @@ -20077,7 +20416,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf( else prefix = 0; } }else{ - if( flag_longlong ){ + if( bArgList ){ + longvalue = (u64)getIntArg(pArgList); + }else if( flag_longlong ){ longvalue = va_arg(ap,u64); }else if( flag_long ){ longvalue = va_arg(ap,unsigned long int); @@ -20097,7 +20438,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( nOut = precision + 10; zOut = zExtra = sqlite3Malloc( nOut ); if( zOut==0 ){ - pAccum->accError = STRACCUM_NOMEM; + setStrAccumError(pAccum, STRACCUM_NOMEM); return; } } @@ -20137,7 +20478,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( case etFLOAT: case etEXP: case etGENERIC: - realvalue = va_arg(ap,double); + if( bArgList ){ + realvalue = getDoubleArg(pArgList); + }else{ + realvalue = va_arg(ap,double); + } #ifdef SQLITE_OMIT_FLOATING_POINT length = 0; #else @@ -20209,7 +20554,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); if( bufpt==0 ){ - pAccum->accError = STRACCUM_NOMEM; + setStrAccumError(pAccum, STRACCUM_NOMEM); return; } } @@ -20292,7 +20637,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf( #endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ break; case etSIZE: - *(va_arg(ap,int*)) = pAccum->nChar; + if( !bArgList ){ + *(va_arg(ap,int*)) = pAccum->nChar; + } length = width = 0; break; case etPERCENT: @@ -20301,7 +20648,12 @@ SQLITE_PRIVATE void sqlite3VXPrintf( length = 1; break; case etCHARX: - c = va_arg(ap,int); + if( bArgList ){ + bufpt = getTextArg(pArgList); + c = bufpt ? bufpt[0] : 0; + }else{ + c = va_arg(ap,int); + } buf[0] = (char)c; if( precision>=0 ){ for(idx=1; idx=0 ){ @@ -20332,7 +20688,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf( int needQuote; char ch; char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ - char *escarg = va_arg(ap,char*); + char *escarg; + + if( bArgList ){ + escarg = getTextArg(pArgList); + }else{ + escarg = va_arg(ap,char*); + } isnull = escarg==0; if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); k = precision; @@ -20344,7 +20706,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( n>etBUFSIZE ){ bufpt = zExtra = sqlite3Malloc( n ); if( bufpt==0 ){ - pAccum->accError = STRACCUM_NOMEM; + setStrAccumError(pAccum, STRACCUM_NOMEM); return; } }else{ @@ -20367,7 +20729,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } case etTOKEN: { Token *pToken = va_arg(ap, Token*); - if( pToken ){ + assert( bArgList==0 ); + if( pToken && pToken->n ){ sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); } length = width = 0; @@ -20377,12 +20740,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf( SrcList *pSrc = va_arg(ap, SrcList*); int k = va_arg(ap, int); struct SrcList_item *pItem = &pSrc->a[k]; + assert( bArgList==0 ); assert( k>=0 && knSrc ); if( pItem->zDatabase ){ - sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1); + sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); sqlite3StrAccumAppend(pAccum, ".", 1); } - sqlite3StrAccumAppend(pAccum, pItem->zName, -1); + sqlite3StrAccumAppendAll(pAccum, pItem->zName); length = width = 0; break; } @@ -20413,7 +20777,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( sqlite3AppendSpace(pAccum, nspace); } } - sqlite3_free(zExtra); + if( zExtra ) sqlite3_free(zExtra); }/* End for loop over the format string */ } /* End of function */ @@ -20421,22 +20785,20 @@ SQLITE_PRIVATE void sqlite3VXPrintf( ** Append N bytes of text from z to the StrAccum object. */ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ - assert( z!=0 || N==0 ); - if( p->accError ){ - testcase(p->accError==STRACCUM_TOOBIG); - testcase(p->accError==STRACCUM_NOMEM); - return; - } - assert( p->zText!=0 || p->nChar==0 ); - if( N<=0 ){ - if( N==0 || z[0]==0 ) return; - N = sqlite3Strlen30(z); - } + assert( z!=0 ); + assert( p->zText!=0 || p->nChar==0 || p->accError ); + assert( N>=0 ); + assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ char *zNew; + if( p->accError ){ + testcase(p->accError==STRACCUM_TOOBIG); + testcase(p->accError==STRACCUM_NOMEM); + return; + } if( !p->useMalloc ){ - p->accError = STRACCUM_TOOBIG; N = p->nAlloc - p->nChar - 1; + setStrAccumError(p, STRACCUM_TOOBIG); if( N<=0 ){ return; } @@ -20446,7 +20808,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ szNew += N + 1; if( szNew > p->mxAlloc ){ sqlite3StrAccumReset(p); - p->accError = STRACCUM_TOOBIG; + setStrAccumError(p, STRACCUM_TOOBIG); return; }else{ p->nAlloc = (int)szNew; @@ -20460,8 +20822,8 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; }else{ - p->accError = STRACCUM_NOMEM; sqlite3StrAccumReset(p); + setStrAccumError(p, STRACCUM_NOMEM); return; } } @@ -20471,6 +20833,14 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ p->nChar += N; } +/* +** Append the complete text of zero-terminated string z[] to the p string. +*/ +SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ + sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); +} + + /* ** Finish off a string by making sure it is zero-terminated. ** Return a pointer to the resulting string. Return a NULL @@ -20488,7 +20858,7 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); }else{ - p->accError = STRACCUM_NOMEM; + setStrAccumError(p, STRACCUM_NOMEM); } } } @@ -20534,7 +20904,7 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); acc.db = db; - sqlite3VXPrintf(&acc, 1, zFormat, ap); + sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.accError==STRACCUM_NOMEM ){ db->mallocFailed = 1; @@ -20690,17 +21060,15 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ } #endif -#ifndef SQLITE_OMIT_TRACE /* ** variable-argument wrapper around sqlite3VXPrintf(). */ -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ va_list ap; va_start(ap,zFormat); - sqlite3VXPrintf(p, 1, zFormat, ap); + sqlite3VXPrintf(p, bFlags, zFormat, ap); va_end(ap); } -#endif /************** End of printf.c **********************************************/ /************** Begin file random.c ******************************************/ @@ -20757,6 +21125,12 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){ sqlite3_mutex_enter(mutex); #endif + if( N<=0 ){ + wsdPrng.isInit = 0; + sqlite3_mutex_leave(mutex); + return; + } + /* Initialize the state of the random number generator once, ** the first time this routine is called. The seed value does ** not need to contain a lot of randomness since we are not @@ -20784,7 +21158,8 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){ wsdPrng.isInit = 1; } - while( N-- ){ + assert( N>0 ); + do{ wsdPrng.i++; t = wsdPrng.s[wsdPrng.i]; wsdPrng.j += t; @@ -20792,7 +21167,7 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){ wsdPrng.s[wsdPrng.j] = t; t += wsdPrng.s[wsdPrng.i]; *(zBuf++) = wsdPrng.s[t]; - } + }while( --N ); sqlite3_mutex_leave(mutex); } @@ -20821,9 +21196,6 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){ sizeof(sqlite3Prng) ); } -SQLITE_PRIVATE void sqlite3PrngResetState(void){ - GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0; -} #endif /* SQLITE_OMIT_BUILTIN_TEST */ /************** End of random.c **********************************************/ @@ -21145,7 +21517,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ sqlite3VdbeMemRelease(pMem); pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); pMem->enc = desiredEnc; - pMem->flags |= (MEM_Term|MEM_Dyn); + pMem->flags |= (MEM_Term); pMem->z = (char*)zOut; pMem->zMalloc = pMem->z; @@ -21273,7 +21645,6 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); - assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed ); assert( m.z || db->mallocFailed ); return m.z; } @@ -21475,18 +21846,17 @@ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){ ** to NULL. */ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ - if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ - db->errCode = err_code; - if( zFormat ){ - char *z; - va_list ap; - va_start(ap, zFormat); - z = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); - }else{ - sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); - } + assert( db!=0 ); + db->errCode = err_code; + if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ + char *z; + va_list ap; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); + }else if( db->pErr ){ + sqlite3ValueSetNull(db->pErr); } } @@ -22362,7 +22732,8 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){ ** Read or write a four-byte big-endian integer value. */ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){ - return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; + testcase( p[0]&0x80 ); + return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; } SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){ p[0] = (u8)(v>>24); @@ -22483,13 +22854,12 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ testcase( iA>0 && LARGEST_INT64 - iA == iB ); testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 ); if( iA>0 && LARGEST_INT64 - iA < iB ) return 1; - *pA += iB; }else{ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 ); testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 ); if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1; - *pA += iB; } + *pA += iB; return 0; } SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ @@ -22513,9 +22883,18 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ iA0 = iA % TWOPOWER32; iB1 = iB/TWOPOWER32; iB0 = iB % TWOPOWER32; - if( iA1*iB1 != 0 ) return 1; - assert( iA1*iB0==0 || iA0*iB1==0 ); - r = iA1*iB0 + iA0*iB1; + if( iA1==0 ){ + if( iB1==0 ){ + *pA *= iB; + return 0; + } + r = iA0*iB1; + }else if( iB1==0 ){ + r = iA1*iB0; + }else{ + /* If both iA1 and iB1 are non-zero, overflow will result */ + return 1; + } testcase( r==(-TWOPOWER31)-1 ); testcase( r==(-TWOPOWER31) ); testcase( r==TWOPOWER31 ); @@ -22703,7 +23082,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){ ** The hashing function. */ static unsigned int strHash(const char *z, int nKey){ - int h = 0; + unsigned int h = 0; assert( nKey>=0 ); while( nKey > 0 ){ h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; @@ -22961,139 +23340,143 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 17 */ "Gosub" OpHelp(""), /* 18 */ "Return" OpHelp(""), /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "Yield" OpHelp(""), - /* 21 */ "HaltIfNull" OpHelp("if r[P3] null then halt"), - /* 22 */ "Halt" OpHelp(""), - /* 23 */ "Integer" OpHelp("r[P2]=P1"), - /* 24 */ "Int64" OpHelp("r[P2]=P4"), - /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 30 */ "Copy" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 32 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 33 */ "CollSeq" OpHelp(""), - /* 34 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 35 */ "MustBeInt" OpHelp(""), - /* 36 */ "RealAffinity" OpHelp(""), - /* 37 */ "Permutation" OpHelp(""), - /* 38 */ "Compare" OpHelp(""), - /* 39 */ "Jump" OpHelp(""), - /* 40 */ "Once" OpHelp(""), - /* 41 */ "If" OpHelp(""), - /* 42 */ "IfNot" OpHelp(""), - /* 43 */ "Column" OpHelp("r[P3]=PX"), - /* 44 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 45 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 46 */ "Count" OpHelp("r[P2]=count()"), - /* 47 */ "ReadCookie" OpHelp(""), - /* 48 */ "SetCookie" OpHelp(""), - /* 49 */ "VerifyCookie" OpHelp(""), - /* 50 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 51 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 52 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 53 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 54 */ "SorterOpen" OpHelp(""), - /* 55 */ "OpenPseudo" OpHelp("content in r[P2@P3]"), - /* 56 */ "Close" OpHelp(""), - /* 57 */ "SeekLt" OpHelp("key=r[P3@P4]"), - /* 58 */ "SeekLe" OpHelp("key=r[P3@P4]"), - /* 59 */ "SeekGe" OpHelp("key=r[P3@P4]"), - /* 60 */ "SeekGt" OpHelp("key=r[P3@P4]"), - /* 61 */ "Seek" OpHelp("intkey=r[P2]"), - /* 62 */ "NoConflict" OpHelp("key=r[P3@P4]"), - /* 63 */ "NotFound" OpHelp("key=r[P3@P4]"), - /* 64 */ "Found" OpHelp("key=r[P3@P4]"), - /* 65 */ "NotExists" OpHelp("intkey=r[P3]"), - /* 66 */ "Sequence" OpHelp("r[P2]=rowid"), - /* 67 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 68 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 69 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 70 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 71 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 72 */ "Delete" OpHelp(""), - /* 73 */ "ResetCount" OpHelp(""), - /* 74 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 75 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 76 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), - /* 77 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), - /* 78 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), - /* 79 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), - /* 80 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), - /* 82 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"), - /* 83 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 84 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 85 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 87 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 88 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 89 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 90 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 91 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 92 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 93 */ "SorterData" OpHelp("r[P2]=data"), - /* 94 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), - /* 95 */ "String8" OpHelp("r[P2]='P4'"), - /* 96 */ "RowKey" OpHelp("r[P2]=key"), - /* 97 */ "RowData" OpHelp("r[P2]=data"), - /* 98 */ "Rowid" OpHelp("r[P2]=rowid"), - /* 99 */ "NullRow" OpHelp(""), - /* 100 */ "Last" OpHelp(""), - /* 101 */ "SorterSort" OpHelp(""), - /* 102 */ "Sort" OpHelp(""), - /* 103 */ "Rewind" OpHelp(""), - /* 104 */ "SorterInsert" OpHelp(""), - /* 105 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 106 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 107 */ "IdxRowid" OpHelp("r[P2]=rowid"), - /* 108 */ "IdxLT" OpHelp("key=r[P3@P4]"), - /* 109 */ "IdxGE" OpHelp("key=r[P3@P4]"), - /* 110 */ "Destroy" OpHelp(""), - /* 111 */ "Clear" OpHelp(""), - /* 112 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), - /* 113 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), - /* 114 */ "ParseSchema" OpHelp(""), - /* 115 */ "LoadAnalysis" OpHelp(""), - /* 116 */ "DropTable" OpHelp(""), - /* 117 */ "DropIndex" OpHelp(""), - /* 118 */ "DropTrigger" OpHelp(""), - /* 119 */ "IntegrityCk" OpHelp(""), - /* 120 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 121 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 122 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 123 */ "Program" OpHelp(""), - /* 124 */ "Param" OpHelp(""), - /* 125 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 126 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), - /* 127 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 128 */ "IfPos" OpHelp("if r[P1]>0 goto P2"), - /* 129 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"), - /* 130 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"), - /* 131 */ "Real" OpHelp("r[P2]=P4"), - /* 132 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 133 */ "IncrVacuum" OpHelp(""), - /* 134 */ "Expire" OpHelp(""), - /* 135 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 136 */ "VBegin" OpHelp(""), - /* 137 */ "VCreate" OpHelp(""), - /* 138 */ "VDestroy" OpHelp(""), - /* 139 */ "VOpen" OpHelp(""), - /* 140 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 141 */ "VNext" OpHelp(""), - /* 142 */ "ToText" OpHelp(""), - /* 143 */ "ToBlob" OpHelp(""), - /* 144 */ "ToNumeric" OpHelp(""), - /* 145 */ "ToInt" OpHelp(""), - /* 146 */ "ToReal" OpHelp(""), - /* 147 */ "VRename" OpHelp(""), - /* 148 */ "Pagecount" OpHelp(""), - /* 149 */ "MaxPgcnt" OpHelp(""), - /* 150 */ "Trace" OpHelp(""), - /* 151 */ "Noop" OpHelp(""), - /* 152 */ "Explain" OpHelp(""), + /* 20 */ "InitCoroutine" OpHelp(""), + /* 21 */ "EndCoroutine" OpHelp(""), + /* 22 */ "Yield" OpHelp(""), + /* 23 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 24 */ "Halt" OpHelp(""), + /* 25 */ "Integer" OpHelp("r[P2]=P1"), + /* 26 */ "Int64" OpHelp("r[P2]=P4"), + /* 27 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 28 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 29 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 30 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 31 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 32 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 33 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 34 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 35 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 36 */ "CollSeq" OpHelp(""), + /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 38 */ "MustBeInt" OpHelp(""), + /* 39 */ "RealAffinity" OpHelp(""), + /* 40 */ "Permutation" OpHelp(""), + /* 41 */ "Compare" OpHelp(""), + /* 42 */ "Jump" OpHelp(""), + /* 43 */ "Once" OpHelp(""), + /* 44 */ "If" OpHelp(""), + /* 45 */ "IfNot" OpHelp(""), + /* 46 */ "Column" OpHelp("r[P3]=PX"), + /* 47 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 48 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 49 */ "Count" OpHelp("r[P2]=count()"), + /* 50 */ "ReadCookie" OpHelp(""), + /* 51 */ "SetCookie" OpHelp(""), + /* 52 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 53 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 54 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 55 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 56 */ "SorterOpen" OpHelp(""), + /* 57 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 58 */ "Close" OpHelp(""), + /* 59 */ "SeekLT" OpHelp(""), + /* 60 */ "SeekLE" OpHelp(""), + /* 61 */ "SeekGE" OpHelp(""), + /* 62 */ "SeekGT" OpHelp(""), + /* 63 */ "Seek" OpHelp("intkey=r[P2]"), + /* 64 */ "NoConflict" OpHelp("key=r[P3@P4]"), + /* 65 */ "NotFound" OpHelp("key=r[P3@P4]"), + /* 66 */ "Found" OpHelp("key=r[P3@P4]"), + /* 67 */ "NotExists" OpHelp("intkey=r[P3]"), + /* 68 */ "Sequence" OpHelp("r[P2]=rowid"), + /* 69 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 70 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), + /* 73 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 74 */ "Delete" OpHelp(""), + /* 75 */ "ResetCount" OpHelp(""), + /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), + /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), + /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), + /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), + /* 82 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), + /* 84 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"), + /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), + /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), + /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), + /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), + /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), + /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), + /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), + /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), + /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), + /* 95 */ "SorterData" OpHelp("r[P2]=data"), + /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), + /* 97 */ "String8" OpHelp("r[P2]='P4'"), + /* 98 */ "RowKey" OpHelp("r[P2]=key"), + /* 99 */ "RowData" OpHelp("r[P2]=data"), + /* 100 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 101 */ "NullRow" OpHelp(""), + /* 102 */ "Last" OpHelp(""), + /* 103 */ "SorterSort" OpHelp(""), + /* 104 */ "Sort" OpHelp(""), + /* 105 */ "Rewind" OpHelp(""), + /* 106 */ "SorterInsert" OpHelp(""), + /* 107 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 108 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 109 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 110 */ "IdxLE" OpHelp("key=r[P3@P4]"), + /* 111 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 112 */ "IdxLT" OpHelp("key=r[P3@P4]"), + /* 113 */ "IdxGE" OpHelp("key=r[P3@P4]"), + /* 114 */ "Destroy" OpHelp(""), + /* 115 */ "Clear" OpHelp(""), + /* 116 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), + /* 117 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), + /* 118 */ "ParseSchema" OpHelp(""), + /* 119 */ "LoadAnalysis" OpHelp(""), + /* 120 */ "DropTable" OpHelp(""), + /* 121 */ "DropIndex" OpHelp(""), + /* 122 */ "DropTrigger" OpHelp(""), + /* 123 */ "IntegrityCk" OpHelp(""), + /* 124 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 125 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), + /* 126 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 127 */ "Program" OpHelp(""), + /* 128 */ "Param" OpHelp(""), + /* 129 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 130 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 131 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 132 */ "IfPos" OpHelp("if r[P1]>0 goto P2"), + /* 133 */ "Real" OpHelp("r[P2]=P4"), + /* 134 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"), + /* 135 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"), + /* 136 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 137 */ "IncrVacuum" OpHelp(""), + /* 138 */ "Expire" OpHelp(""), + /* 139 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 140 */ "VBegin" OpHelp(""), + /* 141 */ "VCreate" OpHelp(""), + /* 142 */ "VDestroy" OpHelp(""), + /* 143 */ "ToText" OpHelp(""), + /* 144 */ "ToBlob" OpHelp(""), + /* 145 */ "ToNumeric" OpHelp(""), + /* 146 */ "ToInt" OpHelp(""), + /* 147 */ "ToReal" OpHelp(""), + /* 148 */ "VOpen" OpHelp(""), + /* 149 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 150 */ "VNext" OpHelp(""), + /* 151 */ "VRename" OpHelp(""), + /* 152 */ "Pagecount" OpHelp(""), + /* 153 */ "MaxPgcnt" OpHelp(""), + /* 154 */ "Init" OpHelp("Start at P2"), + /* 155 */ "Noop" OpHelp(""), + /* 156 */ "Explain" OpHelp(""), }; return azName[i]; } @@ -23185,32 +23568,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ # endif #endif -/* -** These #defines should enable >2GB file support on Posix if the -** underlying operating system supports it. If the OS lacks -** large file support, these should be no-ops. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: RedHat 7.2) but you want your code to work -** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in RedHat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** The previous paragraph was written in 2005. (This paragraph is written -** on 2008-11-28.) These days, all Linux kernels support large files, so -** you should probably leave LFS enabled. But some embedded platforms might -** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 -#endif - /* ** standard include files. */ @@ -23362,6 +23719,12 @@ struct unixFile { #endif }; +/* This variable holds the process id (pid) from when the xRandomness() +** method was called. If xOpen() is called from a different process id, +** indicating that a fork() has occurred, the PRNG will be reset. +*/ +static int randomnessPid = 0; + /* ** Allowed values for the unixFile.ctrlFlags bitmask: */ @@ -24625,6 +24988,15 @@ static int findInodeInfo( return SQLITE_OK; } +/* +** Return TRUE if pFile has been renamed or unlinked since it was first opened. +*/ +static int fileHasMoved(unixFile *pFile){ + struct stat buf; + return pFile->pInode!=0 && + (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); +} + /* ** Check a unixFile that is a database. Verify the following: @@ -24659,10 +25031,7 @@ static void verifyDbFile(unixFile *pFile){ pFile->ctrlFlags |= UNIXFILE_WARNED; return; } - if( pFile->pInode!=0 - && ((rc = osStat(pFile->zPath, &buf))!=0 - || buf.st_ino!=pFile->pInode->fileId.ino) - ){ + if( fileHasMoved(pFile) ){ sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); pFile->ctrlFlags |= UNIXFILE_WARNED; return; @@ -27111,6 +27480,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } + case SQLITE_FCNTL_HAS_MOVED: { + *(int*)pArg = fileHasMoved(pFile); + return SQLITE_OK; + } #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; @@ -27391,7 +27764,7 @@ static int unixShmSystemLock( #ifdef SQLITE_DEBUG { u16 mask; OSTRACE(("SHM-LOCK ")); - mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<31 ? 0xffff : (1<<(ofst+n)) - (1<0 unixFile *pFd = (unixFile *)fd; /* The underlying database file */ UNUSED_PARAMETER(iOff); -#if SQLITE_MAX_MMAP_SIZE>0 /* If p==0 (unmap the entire file) then there must be no outstanding ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), ** then there must be at least one outstanding. */ @@ -28161,6 +28534,10 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ } assert( pFd->nFetchOut>=0 ); +#else + UNUSED_PARAMETER(fd); + UNUSED_PARAMETER(p); + UNUSED_PARAMETER(iOff); #endif return SQLITE_OK; } @@ -28951,6 +29328,16 @@ static int unixOpen( || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); + /* Detect a pid change and reset the PRNG. There is a race condition + ** here such that two or more threads all trying to open databases at + ** the same instant might all reset the PRNG. But multiple resets + ** are harmless. + */ + if( randomnessPid!=getpid() ){ + randomnessPid = getpid(); + sqlite3_randomness(0,0); + } + memset(p, 0, sizeof(unixFile)); if( eType==SQLITE_OPEN_MAIN_DB ){ @@ -29338,18 +29725,18 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** tests repeatable. */ memset(zBuf, 0, nBuf); + randomnessPid = getpid(); #if !defined(SQLITE_TEST) { - int pid, fd, got; + int fd, got; fd = robust_open("/dev/urandom", O_RDONLY, 0); if( fd<0 ){ time_t t; time(&t); memcpy(zBuf, &t, sizeof(t)); - pid = getpid(); - memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid)); - assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf ); - nBuf = sizeof(t) + sizeof(pid); + memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid)); + assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf ); + nBuf = sizeof(t) + sizeof(randomnessPid); }else{ do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR ); robust_close(0, fd, __LINE__); @@ -34087,7 +34474,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { - *(char**)pArg = sqlite3_mprintf("win32"); + *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } @@ -34169,7 +34556,7 @@ static int winDeviceCharacteristics(sqlite3_file *id){ ** During sqlite3_os_init() we do a GetSystemInfo() ** to get the granularity size. */ -SYSTEM_INFO winSysInfo; +static SYSTEM_INFO winSysInfo; #ifndef SQLITE_OMIT_WAL @@ -34192,7 +34579,7 @@ static void winShmEnterMutex(void){ static void winShmLeaveMutex(void){ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } -#ifdef SQLITE_DEBUG +#ifndef NDEBUG static int winShmMutexHeld(void) { return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } @@ -36103,15 +36490,29 @@ static int winFullPathname( ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. */ -/* -** Interfaces for opening a shared library, finding entry points -** within the shared library, and closing the shared library. -*/ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; +#if defined(__CYGWIN__) + int nFull = pVfs->mxPathname+1; + char *zFull = sqlite3MallocZero( nFull ); + void *zConverted = 0; + if( zFull==0 ){ + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ + sqlite3_free(zFull); + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + zConverted = winConvertFromUtf8Filename(zFull); + sqlite3_free(zFull); +#else void *zConverted = winConvertFromUtf8Filename(zFilename); UNUSED_PARAMETER(pVfs); +#endif if( zConverted==0 ){ + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); return 0; } if( osIsNT() ){ @@ -36126,6 +36527,7 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ h = osLoadLibraryA((char*)zConverted); } #endif + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h)); sqlite3_free(zConverted); return (void*)h; } @@ -36134,12 +36536,17 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut); } static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ + FARPROC proc; UNUSED_PARAMETER(pVfs); - return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym); + proc = osGetProcAddressA((HANDLE)pH, zSym); + OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n", + (void*)pH, zSym, (void*)proc)); + return (void(*)(void))proc; } static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ UNUSED_PARAMETER(pVfs); osFreeLibrary((HANDLE)pHandle); + OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle)); } #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ #define winDlOpen 0 @@ -36835,7 +37242,8 @@ struct PCache { int szCache; /* Configured cache size */ int szPage; /* Size of every page in this cache */ int szExtra; /* Size of extra space for each page */ - int bPurgeable; /* True if pages are on backing store */ + u8 bPurgeable; /* True if pages are on backing store */ + u8 eCreate; /* eCreate value for for xFetch() */ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ void *pStress; /* Argument to xStress */ sqlite3_pcache *pCache; /* Pluggable cache module */ @@ -36902,6 +37310,10 @@ static void pcacheRemoveFromDirtyList(PgHdr *pPage){ }else{ assert( pPage==p->pDirty ); p->pDirty = pPage->pDirtyNext; + if( p->pDirty==0 && p->bPurgeable ){ + assert( p->eCreate==1 ); + p->eCreate = 2; + } } pPage->pDirtyNext = 0; pPage->pDirtyPrev = 0; @@ -36922,6 +37334,9 @@ static void pcacheAddToDirtyList(PgHdr *pPage){ if( pPage->pDirtyNext ){ assert( pPage->pDirtyNext->pDirtyPrev==0 ); pPage->pDirtyNext->pDirtyPrev = pPage; + }else if( p->bPurgeable ){ + assert( p->eCreate==2 ); + p->eCreate = 1; } p->pDirty = pPage; if( !p->pDirtyTail ){ @@ -36991,6 +37406,7 @@ SQLITE_PRIVATE void sqlite3PcacheOpen( p->szPage = szPage; p->szExtra = szExtra; p->bPurgeable = bPurgeable; + p->eCreate = 2; p->xStress = xStress; p->pStress = pStress; p->szCache = 100; @@ -37030,7 +37446,7 @@ SQLITE_PRIVATE int sqlite3PcacheFetch( int createFlag, /* If true, create page if it does not exist already */ PgHdr **ppPage /* Write the page here */ ){ - sqlite3_pcache_page *pPage = 0; + sqlite3_pcache_page *pPage; PgHdr *pPgHdr = 0; int eCreate; @@ -37041,8 +37457,12 @@ SQLITE_PRIVATE int sqlite3PcacheFetch( /* If the pluggable cache (sqlite3_pcache*) has not been allocated, ** allocate it now. */ - if( !pCache->pCache && createFlag ){ + if( !pCache->pCache ){ sqlite3_pcache *p; + if( !createFlag ){ + *ppPage = 0; + return SQLITE_OK; + } p = sqlite3GlobalConfig.pcache2.xCreate( pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable ); @@ -37053,11 +37473,16 @@ SQLITE_PRIVATE int sqlite3PcacheFetch( pCache->pCache = p; } - eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty)); - if( pCache->pCache ){ - pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); - } - + /* eCreate defines what to do if the page does not exist. + ** 0 Do not allocate a new page. (createFlag==0) + ** 1 Allocate a new page if doing so is inexpensive. + ** (createFlag==1 AND bPurgeable AND pDirty) + ** 2 Allocate a new page even it doing so is difficult. + ** (createFlag==1 AND !(bPurgeable AND pDirty) + */ + eCreate = createFlag==0 ? 0 : pCache->eCreate; + assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate ); + pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); if( !pPage && eCreate==1 ){ PgHdr *pPg; @@ -37529,6 +37954,7 @@ struct PCache1 { struct PgHdr1 { sqlite3_pcache_page page; unsigned int iKey; /* Key value (page number) */ + u8 isPinned; /* Page in use, not on the LRU list */ PgHdr1 *pNext; /* Next in hash table chain */ PCache1 *pCache; /* Cache that currently owns this page */ PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ @@ -37857,34 +38283,32 @@ static int pcache1ResizeHash(PCache1 *p){ ** LRU list, then this function is a no-op. ** ** The PGroup mutex must be held when this function is called. -** -** If pPage is NULL then this routine is a no-op. */ static void pcache1PinPage(PgHdr1 *pPage){ PCache1 *pCache; PGroup *pGroup; - if( pPage==0 ) return; + assert( pPage!=0 ); + assert( pPage->isPinned==0 ); pCache = pPage->pCache; pGroup = pCache->pGroup; + assert( pPage->pLruNext || pPage==pGroup->pLruTail ); + assert( pPage->pLruPrev || pPage==pGroup->pLruHead ); assert( sqlite3_mutex_held(pGroup->mutex) ); - if( pPage->pLruNext || pPage==pGroup->pLruTail ){ - if( pPage->pLruPrev ){ - pPage->pLruPrev->pLruNext = pPage->pLruNext; - } - if( pPage->pLruNext ){ - pPage->pLruNext->pLruPrev = pPage->pLruPrev; - } - if( pGroup->pLruHead==pPage ){ - pGroup->pLruHead = pPage->pLruNext; - } - if( pGroup->pLruTail==pPage ){ - pGroup->pLruTail = pPage->pLruPrev; - } - pPage->pLruNext = 0; - pPage->pLruPrev = 0; - pPage->pCache->nRecyclable--; + if( pPage->pLruPrev ){ + pPage->pLruPrev->pLruNext = pPage->pLruNext; + }else{ + pGroup->pLruHead = pPage->pLruNext; + } + if( pPage->pLruNext ){ + pPage->pLruNext->pLruPrev = pPage->pLruPrev; + }else{ + pGroup->pLruTail = pPage->pLruPrev; } + pPage->pLruNext = 0; + pPage->pLruPrev = 0; + pPage->isPinned = 1; + pCache->nRecyclable--; } @@ -37916,6 +38340,7 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){ while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ PgHdr1 *p = pGroup->pLruTail; assert( p->pCache->pGroup==pGroup ); + assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); @@ -37943,7 +38368,7 @@ static void pcache1TruncateUnsafe( if( pPage->iKey>=iLimit ){ pCache->nPage--; *pp = pPage->pNext; - pcache1PinPage(pPage); + if( !pPage->isPinned ) pcache1PinPage(pPage); pcache1FreePage(pPage); }else{ pp = &pPage->pNext; @@ -38153,6 +38578,7 @@ static sqlite3_pcache_page *pcache1Fetch( PGroup *pGroup; PgHdr1 *pPage = 0; + assert( offsetof(PgHdr1,page)==0 ); assert( pCache->bPurgeable || createFlag!=1 ); assert( pCache->bPurgeable || pCache->nMin==0 ); assert( pCache->bPurgeable==0 || pCache->nMin==10 ); @@ -38166,8 +38592,11 @@ static sqlite3_pcache_page *pcache1Fetch( } /* Step 2: Abort if no existing page is found and createFlag is 0 */ - if( pPage || createFlag==0 ){ - pcache1PinPage(pPage); + if( pPage ){ + if( !pPage->isPinned ) pcache1PinPage(pPage); + goto fetch_out; + } + if( createFlag==0 ){ goto fetch_out; } @@ -38208,6 +38637,7 @@ static sqlite3_pcache_page *pcache1Fetch( )){ PCache1 *pOther; pPage = pGroup->pLruTail; + assert( pPage->isPinned==0 ); pcache1RemoveFromHash(pPage); pcache1PinPage(pPage); pOther = pPage->pCache; @@ -38244,6 +38674,7 @@ static sqlite3_pcache_page *pcache1Fetch( pPage->pCache = pCache; pPage->pLruPrev = 0; pPage->pLruNext = 0; + pPage->isPinned = 1; *(void **)pPage->page.pExtra = 0; pCache->apHash[h] = pPage; } @@ -38253,7 +38684,7 @@ fetch_out: pCache->iMaxKey = iKey; } pcache1LeaveMutex(pGroup); - return &pPage->page; + return (sqlite3_pcache_page*)pPage; } @@ -38279,6 +38710,7 @@ static void pcache1Unpin( */ assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage ); + assert( pPage->isPinned==1 ); if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ pcache1RemoveFromHash(pPage); @@ -38294,6 +38726,7 @@ static void pcache1Unpin( pGroup->pLruHead = pPage; } pCache->nRecyclable++; + pPage->isPinned = 0; } pcache1LeaveMutex(pCache->pGroup); @@ -38420,6 +38853,7 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ #ifdef SQLITE_PCACHE_SEPARATE_HEADER nFree += sqlite3MemSize(p); #endif + assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); @@ -38444,6 +38878,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( PgHdr1 *p; int nRecyclable = 0; for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){ + assert( p->isPinned==0 ); nRecyclable++; } *pnCurrent = pcache1.grp.nCurrentPage; @@ -40130,15 +40565,12 @@ static char *print_pager_state(Pager *p){ static int subjRequiresPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; PagerSavepoint *p; - Pgno pgno; + Pgno pgno = pPg->pgno; int i; - if( pPager->nSavepoint ){ - pgno = pPg->pgno; - for(i=0; inSavepoint; i++){ - p = &pPager->aSavepoint[i]; - if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ - return 1; - } + for(i=0; inSavepoint; i++){ + p = &pPager->aSavepoint[i]; + if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ + return 1; } } return 0; @@ -40147,8 +40579,8 @@ static int subjRequiresPage(PgHdr *pPg){ /* ** Return true if the page is already in the journal file. */ -static int pageInJournal(PgHdr *pPg){ - return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno); +static int pageInJournal(Pager *pPager, PgHdr *pPg){ + return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno); } /* @@ -40355,6 +40787,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ || szJ<16 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) || len>=nMaster + || len==0 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) || memcmp(aMagic, aJournalMagic, 8) @@ -40791,7 +41224,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ ** already in memory. */ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *p; /* Return value */ + PgHdr *p = 0; /* Return value */ /* It is not possible for a call to PcacheFetch() with createFlag==0 to ** fail, since no attempt to allocate dynamic memory will be made. @@ -41095,7 +41528,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ PgHdr *p = pager_lookup(pPager, 1); if( p ){ p->pageHash = 0; - sqlite3PagerUnref(p); + sqlite3PagerUnrefNotNull(p); } } #endif @@ -41124,6 +41557,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ rc = pager_truncate(pPager, pPager->dbSize); } + if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } + if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ @@ -41937,7 +42375,7 @@ end_playback: if( rc==SQLITE_OK && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ - rc = sqlite3PagerSync(pPager); + rc = sqlite3PagerSync(pPager, 0); } if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); @@ -42083,7 +42521,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){ if( rc==SQLITE_OK ){ pPager->xReiniter(pPg); } - sqlite3PagerUnref(pPg); + sqlite3PagerUnrefNotNull(pPg); } } @@ -43438,7 +43876,7 @@ static int subjournalPage(PgHdr *pPg){ assert( isOpen(pPager->jfd) || pagerUseWal(pPager) ); assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 ); assert( pagerUseWal(pPager) - || pageInJournal(pPg) + || pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); rc = openSubJournal(pPager); @@ -43903,6 +44341,30 @@ SQLITE_PRIVATE int sqlite3PagerOpen( } +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still were it ought +** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +** code from sqlite3OsAccess()) if the database has gone missing. +*/ +static int databaseIsUnmoved(Pager *pPager){ + int bHasMoved = 0; + int rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_NOTFOUND ){ + /* If the HAS_MOVED file-control is unimplemented, assume that the file + ** has not been moved. That is the historical behavior of SQLite: prior to + ** version 3.8.3, it never checked */ + rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bHasMoved ){ + rc = SQLITE_READONLY_DBMOVED; + } + return rc; +} + /* ** This function is called after transitioning from PAGER_UNLOCK to @@ -43968,15 +44430,17 @@ static int hasHotJournal(Pager *pPager, int *pExists){ if( rc==SQLITE_OK && !locked ){ Pgno nPage; /* Number of pages in database file */ - /* Check the size of the database file. If it consists of 0 pages, - ** then delete the journal file. See the header comment above for - ** the reasoning here. Delete the obsolete journal file under - ** a RESERVED lock to avoid race conditions and to avoid violating - ** [H33020]. - */ rc = pagerPagecount(pPager, &nPage); if( rc==SQLITE_OK ){ - if( nPage==0 ){ + /* If the database is zero pages in size, that means that either (1) the + ** journal is a remnant from a prior database with the same name where + ** the database file but not the journal was deleted, or (2) the initial + ** transaction that populates a new database is being rolled back. + ** In either case, the journal file can be deleted. However, take care + ** not to delete the journal file if it is already open due to + ** journal_mode=PERSIST. + */ + if( nPage==0 && !jrnlOpen ){ sqlite3BeginBenignMalloc(); if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){ sqlite3OsDelete(pVfs, pPager->zJournal, 0); @@ -44374,7 +44838,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire( if( rc!=SQLITE_OK ) goto pager_acquire_err; } - if( iFrame==0 && bMmapOk ){ + if( bMmapOk && iFrame==0 ){ void *pData = 0; rc = sqlite3OsFetch(pPager->fd, @@ -44515,16 +44979,19 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ ** are released, a rollback occurs and the lock on the database is ** removed. */ -SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ - if( pPg ){ - Pager *pPager = pPg->pPager; - if( pPg->flags & PGHDR_MMAP ){ - pagerReleaseMapPage(pPg); - }else{ - sqlite3PcacheRelease(pPg); - } - pagerUnlockIfUnused(pPager); +SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ + Pager *pPager; + assert( pPg!=0 ); + pPager = pPg->pPager; + if( pPg->flags & PGHDR_MMAP ){ + pagerReleaseMapPage(pPg); + }else{ + sqlite3PcacheRelease(pPg); } + pagerUnlockIfUnused(pPager); +} +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ + if( pPg ) sqlite3PagerUnrefNotNull(pPg); } /* @@ -44579,13 +45046,19 @@ static int pager_open_journal(Pager *pPager){ (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): (SQLITE_OPEN_MAIN_JOURNAL) ); - #ifdef SQLITE_ENABLE_ATOMIC_WRITE - rc = sqlite3JournalOpen( - pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) - ); - #else - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); - #endif + + /* Verify that the database still has the same name as it did when + ** it was originally opened. */ + rc = databaseIsUnmoved(pPager); + if( rc==SQLITE_OK ){ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + rc = sqlite3JournalOpen( + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + ); +#else + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); +#endif + } } assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); } @@ -44706,9 +45179,9 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory ** of any open savepoints as appropriate. */ static int pager_write(PgHdr *pPg){ - void *pData = pPg->pData; Pager *pPager = pPg->pPager; int rc = SQLITE_OK; + int inJournal; /* This routine is not called unless a write-transaction has already ** been started. The journal file may or may not be open at this point. @@ -44719,14 +45192,8 @@ static int pager_write(PgHdr *pPg){ || pPager->eState==PAGER_WRITER_DBMOD ); assert( assert_pager_state(pPager) ); - - /* If an error has been previously detected, report the same error - ** again. This should not happen, but the check provides robustness. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - /* Higher-level routines never call this function if database is not - ** writable. But check anyway, just for robustness. */ - if( NEVER(pPager->readOnly) ) return SQLITE_PERM; + assert( pPager->errCode==0 ); + assert( pPager->readOnly==0 ); CHECK_PAGE(pPg); @@ -44750,7 +45217,8 @@ static int pager_write(PgHdr *pPg){ ** to the journal then we can return right away. */ sqlite3PcacheMakeDirty(pPg); - if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){ + inJournal = pageInJournal(pPager, pPg); + if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){ assert( !pagerUseWal(pPager) ); }else{ @@ -44758,7 +45226,7 @@ static int pager_write(PgHdr *pPg){ ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ - if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){ + if( !inJournal && !pagerUseWal(pPager) ){ assert( pagerUseWal(pPager)==0 ); if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){ u32 cksum; @@ -44771,7 +45239,7 @@ static int pager_write(PgHdr *pPg){ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); assert( pPager->journalHdr<=pPager->journalOff ); - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); cksum = pager_cksum(pPager, (u8*)pData2); /* Even if an IO or diskfull error occurs while journalling the @@ -44823,7 +45291,7 @@ static int pager_write(PgHdr *pPg){ ** the statement journal format differs from the standard journal format ** in that it omits the checksums and the header. */ - if( subjRequiresPage(pPg) ){ + if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){ rc = subjournalPage(pPg); } } @@ -44855,19 +45323,19 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( pPager->eState!=PAGER_ERROR ); assert( assert_pager_state(pPager) ); - if( nPagePerSector>1 ){ + if( pPager->sectorSize > (u32)pPager->pageSize ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage = 0; /* Number of pages starting at pg1 to journal */ int ii; /* Loop counter */ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow ** a journal header to be written between the pages journaled by @@ -44906,14 +45374,14 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; } - sqlite3PagerUnref(pPage); + sqlite3PagerUnrefNotNull(pPage); } } }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; } - sqlite3PagerUnref(pPage); + sqlite3PagerUnrefNotNull(pPage); } } @@ -44929,7 +45397,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ PgHdr *pPage = pager_lookup(pPager, pg1+ii); if( pPage ){ pPage->flags |= PGHDR_NEED_SYNC; - sqlite3PagerUnref(pPage); + sqlite3PagerUnrefNotNull(pPage); } } } @@ -45082,17 +45550,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ ** If successful, or if called on a pager for which it is a no-op, this ** function returns SQLITE_OK. Otherwise, an IO error code is returned. */ -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; - if( !pPager->noSync ){ + + if( isOpen(pPager->fd) ){ + void *pArg = (void*)zMaster; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } + if( rc==SQLITE_OK && !pPager->noSync ){ assert( !MEMDB ); rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); - }else if( isOpen(pPager->fd) ){ - assert( !MEMDB ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0); - if( rc==SQLITE_NOTFOUND ){ - rc = SQLITE_OK; - } } return rc; } @@ -45291,7 +45759,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( /* Finally, sync the database file. */ if( !noSync ){ - rc = sqlite3PagerSync(pPager); + rc = sqlite3PagerSync(pPager, zMaster); } IOTRACE(("DBSYNC %p\n", pPager)) } @@ -45420,7 +45888,9 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT - || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR ); + || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR + || rc==SQLITE_CANTOPEN + ); /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error persistent. @@ -45823,7 +46293,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ needSyncPgno = pPg->pgno; assert( pPager->journalMode==PAGER_JOURNALMODE_OFF || - pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize ); + pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); assert( pPg->flags&PGHDR_DIRTY ); } @@ -45857,7 +46327,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i if( MEMDB ){ assert( pPgOld ); sqlite3PcacheMove(pPgOld, origPgno); - sqlite3PagerUnref(pPgOld); + sqlite3PagerUnrefNotNull(pPgOld); } if( needSyncPgno ){ @@ -45886,7 +46356,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i } pPgHdr->flags |= PGHDR_NEED_SYNC; sqlite3PcacheMakeDirty(pPgHdr); - sqlite3PagerUnref(pPgHdr); + sqlite3PagerUnrefNotNull(pPgHdr); } return SQLITE_OK; @@ -47602,7 +48072,7 @@ SQLITE_PRIVATE int sqlite3WalOpen( sqlite3OsClose(pRet->pWalFd); sqlite3_free(pRet); }else{ - int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd); + int iDC = sqlite3OsDeviceCharacteristics(pDbFd); if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ pRet->padToSectorBoundary = 0; @@ -48973,7 +49443,7 @@ static int walWriteToLog( iAmt -= iFirstAmt; pContent = (void*)(iFirstAmt + (char*)pContent); assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); - rc = sqlite3OsSync(p->pFd, p->syncFlags); + rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK); if( iAmt==0 || rc ) return rc; } rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); @@ -49911,7 +50381,6 @@ struct BtCursor { Pgno *aOverflow; /* Cache of overflow page locations */ #endif Pgno pgnoRoot; /* The root page of this tree */ - sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */ CellInfo info; /* A parse of the cell we are pointing at */ i64 nKey; /* Size of pKey, or last integer key */ void *pKey; /* Saved key that was cursor's last known position */ @@ -51895,13 +52364,12 @@ static void zeroPage(MemPage *pPage, int flags){ memset(&data[hdr], 0, pBt->usableSize - hdr); } data[hdr] = (char)flags; - first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); + first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8); memset(&data[hdr+1], 0, 4); data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); pPage->nFree = (u16)(pBt->usableSize - first); decodeFlags(pPage, flags); - pPage->hdrOffset = hdr; pPage->cellOffset = first; pPage->aDataEnd = &data[pBt->usableSize]; pPage->aCellIdx = &data[first]; @@ -52005,7 +52473,7 @@ static int getAndInitPage( rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeGetPage(pBt, pgno, ppPage, bReadonly); - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); @@ -52026,10 +52494,11 @@ static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->aData ); assert( pPage->pBt ); + assert( pPage->pDbPage!=0 ); assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3PagerUnref(pPage->pDbPage); + sqlite3PagerUnrefNotNull(pPage->pDbPage); } } @@ -53984,7 +54453,6 @@ static int btreeCursor( } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; - pCur->cachedRowid = 0; return SQLITE_OK; } SQLITE_PRIVATE int sqlite3BtreeCursor( @@ -54025,36 +54493,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ memset(p, 0, offsetof(BtCursor, iPage)); } -/* -** Set the cached rowid value of every cursor in the same database file -** as pCur and having the same root page number as pCur. The value is -** set to iRowid. -** -** Only positive rowid values are considered valid for this cache. -** The cache is initialized to zero, indicating an invalid cache. -** A btree will work fine with zero or negative rowids. We just cannot -** cache zero or negative rowids, which means tables that use zero or -** negative rowids might run a little slower. But in practice, zero -** or negative rowids are very uncommon so this should not be a problem. -*/ -SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){ - BtCursor *p; - for(p=pCur->pBt->pCursor; p; p=p->pNext){ - if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid; - } - assert( pCur->cachedRowid==iRowid ); -} - -/* -** Return the cached rowid for the given cursor. A negative or zero -** return value indicates that the rowid cache is invalid and should be -** ignored. If the rowid cache has never before been set, then a -** zero is returned. -*/ -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){ - return pCur->cachedRowid; -} - /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. @@ -54106,7 +54544,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); - assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); + assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else #define assertCellInfo(x) @@ -54545,10 +54983,10 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p /* ** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of -** the key if skipKey==0 and it points to the beginning of data if -** skipKey==1. The number of bytes of available key/data is written -** into *pAmt. If *pAmt==0, then the value returned will not be -** a valid pointer. +** the key if index btrees (pPage->intKey==0) and is the data for +** table btrees (pPage->intKey==1). The number of bytes of available +** key/data is written into *pAmt. If *pAmt==0, then the value +** returned will not be a valid pointer. ** ** This routine is an optimization. It is common for the entire key ** and data to fit on the local page and for there to be no overflow @@ -54561,41 +54999,21 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p ** page of the database. The data might change or move the next time ** any btree routine is called. */ -static const unsigned char *fetchPayload( +static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ - u32 *pAmt, /* Write the number of available bytes here */ - int skipKey /* read beginning at data if this is true */ + u32 *pAmt /* Write the number of available bytes here */ ){ - unsigned char *aPayload; - MemPage *pPage; - u32 nKey; - u32 nLocal; - assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); - pPage = pCur->apPage[pCur->iPage]; - assert( pCur->aiIdx[pCur->iPage]nCell ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); if( pCur->info.nSize==0 ){ btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage], &pCur->info); } - aPayload = pCur->info.pCell; - aPayload += pCur->info.nHeader; - if( pPage->intKey ){ - nKey = 0; - }else{ - nKey = (int)pCur->info.nKey; - } - if( skipKey ){ - aPayload += nKey; - nLocal = pCur->info.nLocal - nKey; - }else{ - nLocal = pCur->info.nLocal; - assert( nLocal<=nKey ); - } - *pAmt = nLocal; - return aPayload; + *pAmt = pCur->info.nLocal; + return (void*)(pCur->info.pCell + pCur->info.nHeader); } @@ -54614,22 +55032,10 @@ static const unsigned char *fetchPayload( ** in the common case where no overflow pages are used. */ SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){ - const void *p = 0; - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorHoldsMutex(pCur) ); - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - p = (const void*)fetchPayload(pCur, pAmt, 0); - } - return p; + return fetchPayload(pCur, pAmt); } SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){ - const void *p = 0; - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorHoldsMutex(pCur) ); - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - p = (const void*)fetchPayload(pCur, pAmt, 1); - } - return p; + return fetchPayload(pCur, pAmt); } @@ -54748,8 +55154,6 @@ static void moveToParent(BtCursor *pCur){ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; - Btree *p = pCur->pBtree; - BtShared *pBt = p->pBt; assert( cursorHoldsMutex(pCur) ); assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); @@ -54764,56 +55168,52 @@ static int moveToRoot(BtCursor *pCur){ } if( pCur->iPage>=0 ){ - int i; - for(i=1; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - } - pCur->iPage = 0; + while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]); }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_OK; }else{ - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], + rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } pCur->iPage = 0; - - /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor - ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is - ** NULL, the caller expects a table b-tree. If this is not the case, - ** return an SQLITE_CORRUPT error. */ - assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 ); - if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){ - return SQLITE_CORRUPT_BKPT; - } } - - /* Assert that the root page is of the correct type. This must be the - ** case as the call to this function that loaded the root-page (either - ** this call or a previous invocation) would have detected corruption - ** if the assumption were not true, and it is not possible for the flags - ** byte to have been modified while this cursor is holding a reference - ** to the page. */ pRoot = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); - assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey ); + + /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor + ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is + ** NULL, the caller expects a table b-tree. If this is not the case, + ** return an SQLITE_CORRUPT error. + ** + ** Earlier versions of SQLite assumed that this test could not fail + ** if the root page was already loaded when this function was called (i.e. + ** if pCur->iPage>=0). But this is not so if the database is corrupted + ** in such a way that page pRoot is linked into a second b-tree table + ** (or the freelist). */ + assert( pRoot->intKey==1 || pRoot->intKey==0 ); + if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ + return SQLITE_CORRUPT_BKPT; + } pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->atLast = 0; pCur->validNKey = 0; - if( pRoot->nCell==0 && !pRoot->leaf ){ + if( pRoot->nCell>0 ){ + pCur->eState = CURSOR_VALID; + }else if( !pRoot->leaf ){ Pgno subpage; if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); pCur->eState = CURSOR_VALID; rc = moveToChild(pCur, subpage); }else{ - pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID); + pCur->eState = CURSOR_INVALID; } return rc; } @@ -54969,6 +55369,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( int *pRes /* Write search results here */ ){ int rc; + RecordCompare xRecordCompare; assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); @@ -54990,6 +55391,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( } } + if( pIdxKey ){ + xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); + assert( pIdxKey->default_rc==1 + || pIdxKey->default_rc==0 + || pIdxKey->default_rc==-1 + ); + }else{ + xRecordCompare = 0; /* All keys are integers */ + } + rc = moveToRoot(pCur); if( rc ){ return rc; @@ -55022,7 +55433,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( assert( biasRight==0 || biasRight==1 ); idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ pCur->aiIdx[pCur->iPage] = (u16)idx; - if( pPage->intKey ){ + if( xRecordCompare==0 ){ for(;;){ i64 nCellKey; pCell = findCell(pPage, idx) + pPage->childPtrSize; @@ -55069,22 +55480,19 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( ** 2 bytes of the cell. */ nCell = pCell[0]; - if( nCell<=pPage->max1bytePayload - /* && (pCell+nCell)aDataEnd */ - ){ + if( nCell<=pPage->max1bytePayload ){ /* This branch runs if the record-size field of the cell is a ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); - c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal - /* && (pCell+nCell+2)<=pPage->aDataEnd */ ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); - c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0); }else{ /* The record flows over onto one or more overflow pages. In ** this case the whole cell needs to be parsed, a buffer allocated @@ -55105,7 +55513,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( sqlite3_free(pCellKey); goto moveto_finish; } - c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); + c = xRecordCompare(nCell, pCellKey, pIdxKey, 0); sqlite3_free(pCellKey); } if( c<0 ){ @@ -55170,6 +55578,15 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){ ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. +** +** The calling function will set *pRes to 0 or 1. The initial *pRes value +** will be 1 if the cursor being stepped corresponds to an SQL index and +** if this routine could have been skipped if that SQL index had been +** a unique index. Otherwise the caller will have set *pRes to zero. +** Zero is the common case. The btree implementation is free to use the +** initial *pRes value as a hint to improve performance, but the current +** SQLite btree implementation does not. (Note that the comdb2 btree +** implementation does use this hint, however.) */ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; @@ -55178,6 +55595,7 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ assert( cursorHoldsMutex(pCur) ); assert( pRes!=0 ); + assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); if( pCur->eState!=CURSOR_VALID ){ rc = restoreCursorPosition(pCur); @@ -55256,6 +55674,15 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ ** successful then set *pRes=0. If the cursor ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. +** +** The calling function will set *pRes to 0 or 1. The initial *pRes value +** will be 1 if the cursor being stepped corresponds to an SQL index and +** if this routine could have been skipped if that SQL index had been +** a unique index. Otherwise the caller will have set *pRes to zero. +** Zero is the common case. The btree implementation is free to use the +** initial *pRes value as a hint to improve performance, but the current +** SQLite btree implementation does not. (Note that the comdb2 btree +** implementation does use this hint, however.) */ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; @@ -55263,6 +55690,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ assert( cursorHoldsMutex(pCur) ); assert( pRes!=0 ); + assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); pCur->atLast = 0; if( pCur->eState!=CURSOR_VALID ){ @@ -55642,6 +56070,7 @@ end_allocate_page: if( rc==SQLITE_OK ){ if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ releasePage(*ppPage); + *ppPage = 0; return SQLITE_CORRUPT_BKPT; } (*ppPage)->isInit = 0; @@ -55903,7 +56332,7 @@ static int fillInCell( nHeader += 4; } if( pPage->hasData ){ - nHeader += putVarint(&pCell[nHeader], nData+nZero); + nHeader += putVarint32(&pCell[nHeader], nData+nZero); }else{ nData = nZero = 0; } @@ -56031,7 +56460,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ u32 pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ - u8 *endPtr; /* End of loop */ int rc; /* The return code */ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ @@ -56056,13 +56484,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ *pRC = rc; return; } - endPtr = &pPage->aCellIdx[2*pPage->nCell - 2]; - assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */ - while( ptrnCell--; + memmove(ptr, ptr+2, 2*(pPage->nCell - idx)); put2byte(&data[hdr+3], pPage->nCell); pPage->nFree += 2; } @@ -56099,9 +56522,6 @@ static void insertCell( int ins; /* Index in data[] where new cell pointer is inserted */ int cellOffset; /* Address of first cell pointer in data[] */ u8 *data; /* The content of the whole page */ - u8 *ptr; /* Used for moving information around in data[] */ - u8 *endPtr; /* End of the loop */ - int nSkip = (iChild ? 4 : 0); if( *pRC ) return; @@ -56152,13 +56572,7 @@ static void insertCell( if( iChild ){ put4byte(&data[idx], iChild); } - ptr = &data[end]; - endPtr = &data[ins]; - assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */ - while( ptr>endPtr ){ - *(u16*)ptr = *(u16*)&ptr[-2]; - ptr -= 2; - } + memmove(&data[ins+2], &data[ins], end-ins); put2byte(&data[ins], idx); put2byte(&data[pPage->hdrOffset+3], pPage->nCell); #ifndef SQLITE_OMIT_AUTOVACUUM @@ -57373,11 +57787,17 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); if( rc ) return rc; - /* If this is an insert into a table b-tree, invalidate any incrblob - ** cursors open on the row being replaced (assuming this is a replace - ** operation - if it is not, the following is a no-op). */ if( pCur->pKeyInfo==0 ){ + /* If this is an insert into a table b-tree, invalidate any incrblob + ** cursors open on the row being replaced */ invalidateIncrblobCursors(p, nKey, 0); + + /* If the cursor is currently on the last row and we are appending a + ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto() + ** call */ + if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){ + loc = -1; + } } if( !loc ){ @@ -57447,8 +57867,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** row without seeking the cursor. This can be a big performance boost. */ pCur->info.nSize = 0; - pCur->validNKey = 0; if( rc==SQLITE_OK && pPage->nOverflow ){ + pCur->validNKey = 0; rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() @@ -57503,7 +57923,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ ** sub-tree headed by the child page of the cell being deleted. This makes ** balancing the tree following the delete operation easier. */ if( !pPage->leaf ){ - int notUsed; + int notUsed = 0; rc = sqlite3BtreePrevious(pCur, ¬Used); if( rc ) return rc; } @@ -57756,6 +58176,7 @@ static int clearDatabasePage( int rc; unsigned char *pCell; int i; + int hdr; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ @@ -57764,6 +58185,7 @@ static int clearDatabasePage( rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; + hdr = pPage->hdrOffset; for(i=0; inCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ @@ -57774,7 +58196,7 @@ static int clearDatabasePage( if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ - rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange); + rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; }else if( pnChange ){ assert( pPage->intKey ); @@ -57783,7 +58205,7 @@ static int clearDatabasePage( if( freePageFlag ){ freePage(pPage, &rc); }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ - zeroPage(pPage, pPage->aData[0] | PTF_LEAF); + zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF); } cleardatabasepage_out: @@ -58120,7 +58542,7 @@ static void checkAppendMsg( sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); } if( zMsg1 ){ - sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1); + sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1); } sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); va_end(ap); @@ -59414,7 +59836,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ /* Sync the database file to disk. */ if( rc==SQLITE_OK ){ - rc = sqlite3PagerSync(pDestPager); + rc = sqlite3PagerSync(pDestPager, 0); } }else{ sqlite3PagerTruncateImage(pDestPager, nDestTruncate); @@ -59489,10 +59911,10 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; - sqlite3Error(p->pDestDb, rc, 0); - - /* Exit the mutexes and free the backup context structure. */ if( p->pDestDb ){ + sqlite3Error(p->pDestDb, rc, 0); + + /* Exit the mutexes and free the backup context structure. */ sqlite3LeaveMutexAndCloseZombie(p->pDestDb); } sqlite3BtreeLeave(p->pSrc); @@ -59655,6 +60077,42 @@ copy_finished: ** name sqlite_value */ +#ifdef SQLITE_DEBUG +/* +** Check invariants on a Mem object. +** +** This routine is intended for use inside of assert() statements, like +** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); +*/ +SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ + /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor + ** function for Mem.z + */ + assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); + assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 ); + + /* If p holds a string or blob, the Mem.z must point to exactly + ** one of the following: + ** + ** (1) Memory in Mem.zMalloc and managed by the Mem object + ** (2) Memory to be freed using Mem.xDel + ** (3) An ephermal string or blob + ** (4) A static string or blob + */ + if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){ + assert( + ((p->z==p->zMalloc)? 1 : 0) + + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 + ); + } + + return 1; +} +#endif + + /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is @@ -59696,57 +60154,51 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ /* ** Make sure pMem->z points to a writable allocation of at least -** n bytes. -** -** If the third argument passed to this function is true, then memory -** cell pMem must contain a string or blob. In this case the content is -** preserved. Otherwise, if the third parameter to this function is false, -** any current string or blob value may be discarded. -** -** This function sets the MEM_Dyn flag and clears any xDel callback. -** It also clears MEM_Ephem and MEM_Static. If the preserve flag is -** not set, Mem.n is zeroed. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ - assert( 1 >= - ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + - (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + - ((pMem->flags&MEM_Ephem) ? 1 : 0) + - ((pMem->flags&MEM_Static) ? 1 : 0) - ); +** min(n,32) bytes. +** +** If the bPreserve argument is true, then copy of the content of +** pMem->z into the new allocation. pMem must be either a string or +** blob if bPreserve is true. If bPreserve is false, any prior content +** in pMem->z is discarded. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ + assert( sqlite3VdbeCheckMemInvariants(pMem) ); assert( (pMem->flags&MEM_RowSet)==0 ); - /* If the preserve flag is set to true, then the memory cell must already + /* If the bPreserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ - assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + testcase( bPreserve && pMem->z==0 ); - if( n<32 ) n = 32; - if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ + if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); - preserve = 0; + bPreserve = 0; }else{ sqlite3DbFree(pMem->db, pMem->zMalloc); pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } + if( pMem->zMalloc==0 ){ + VdbeMemRelease(pMem); + pMem->z = 0; + pMem->flags = MEM_Null; + return SQLITE_NOMEM; + } } - if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ + if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } - if( pMem->flags&MEM_Dyn && pMem->xDel ){ - assert( pMem->xDel!=SQLITE_DYNAMIC ); + if( (pMem->flags&MEM_Dyn)!=0 ){ + assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC ); pMem->xDel((void *)(pMem->z)); } pMem->z = pMem->zMalloc; - if( pMem->z==0 ){ - pMem->flags = MEM_Null; - }else{ - pMem->flags &= ~(MEM_Ephem|MEM_Static); - } + pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static); pMem->xDel = 0; - return (pMem->z ? SQLITE_OK : SQLITE_NOMEM); + return SQLITE_OK; } /* @@ -59913,9 +60365,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); - }else if( p->flags&MEM_Dyn && p->xDel ){ + }else if( p->flags&MEM_Dyn ){ assert( (p->flags&MEM_RowSet)==0 ); - assert( p->xDel!=SQLITE_DYNAMIC ); + assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); p->xDel((void *)p->z); p->xDel = 0; }else if( p->flags&MEM_RowSet ){ @@ -59928,14 +60380,17 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and -** (Mem.type==SQLITE_TEXT). +** (Mem.flags==MEM_Str). */ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ + assert( sqlite3VdbeCheckMemInvariants(p) ); VdbeMemRelease(p); - sqlite3DbFree(p->db, p->zMalloc); + if( p->zMalloc ){ + sqlite3DbFree(p->db, p->zMalloc); + p->zMalloc = 0; + } p->z = 0; - p->zMalloc = 0; - p->xDel = 0; + assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */ } /* @@ -60117,7 +60572,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ sqlite3RowSetClear(pMem->u.pRowSet); } MemSetTypeFlag(pMem, MEM_Null); - pMem->type = SQLITE_NULL; +} +SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){ + sqlite3VdbeMemSetNull((Mem*)p); } /* @@ -60127,7 +60584,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Blob|MEM_Zero; - pMem->type = SQLITE_BLOB; pMem->n = 0; if( n<0 ) n = 0; pMem->u.nZero = n; @@ -60150,7 +60606,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ sqlite3VdbeMemRelease(pMem); pMem->u.i = val; pMem->flags = MEM_Int; - pMem->type = SQLITE_INTEGER; } #ifndef SQLITE_OMIT_FLOATING_POINT @@ -60165,7 +60620,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ sqlite3VdbeMemRelease(pMem); pMem->r = val; pMem->flags = MEM_Real; - pMem->type = SQLITE_FLOAT; } } #endif @@ -60221,7 +60675,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ Mem *pX; for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){ if( pX->pScopyFrom==pMem ){ - pX->flags |= MEM_Invalid; + pX->flags |= MEM_Undefined; pX->pScopyFrom = 0; } } @@ -60232,7 +60686,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ /* ** Size of struct Mem not including the Mem.zMalloc member. */ -#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc)) +#define MEMCELLSIZE offsetof(Mem,zMalloc) /* ** Make an shallow copy of pFrom into pTo. Prior contents of @@ -60263,6 +60717,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ VdbeMemRelease(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; + pTo->xDel = 0; if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ @@ -60373,7 +60828,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( pMem->n = nByte; pMem->flags = flags; pMem->enc = (enc==0 ? SQLITE_UTF8 : enc); - pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT); #ifndef SQLITE_OMIT_UTF16 if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ @@ -60388,119 +60842,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( return SQLITE_OK; } -/* -** Compare the values contained by the two memory cells, returning -** negative, zero or positive if pMem1 is less than, equal to, or greater -** than pMem2. Sorting order is NULL's first, followed by numbers (integers -** and reals) sorted numerically, followed by text ordered by the collating -** sequence pColl and finally blob's ordered by memcmp(). -** -** Two NULL values are considered equal by this function. -*/ -SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ - int rc; - int f1, f2; - int combined_flags; - - f1 = pMem1->flags; - f2 = pMem2->flags; - combined_flags = f1|f2; - assert( (combined_flags & MEM_RowSet)==0 ); - - /* If one value is NULL, it is less than the other. If both values - ** are NULL, return 0. - */ - if( combined_flags&MEM_Null ){ - return (f2&MEM_Null) - (f1&MEM_Null); - } - - /* If one value is a number and the other is not, the number is less. - ** If both are numbers, compare as reals if one is a real, or as integers - ** if both values are integers. - */ - if( combined_flags&(MEM_Int|MEM_Real) ){ - double r1, r2; - if( (f1 & f2 & MEM_Int)!=0 ){ - if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return 1; - return 0; - } - if( (f1&MEM_Real)!=0 ){ - r1 = pMem1->r; - }else if( (f1&MEM_Int)!=0 ){ - r1 = (double)pMem1->u.i; - }else{ - return 1; - } - if( (f2&MEM_Real)!=0 ){ - r2 = pMem2->r; - }else if( (f2&MEM_Int)!=0 ){ - r2 = (double)pMem2->u.i; - }else{ - return -1; - } - if( r1r2 ) return 1; - return 0; - } - - /* If one value is a string and the other is a blob, the string is less. - ** If both are strings, compare using the collating functions. - */ - if( combined_flags&MEM_Str ){ - if( (f1 & MEM_Str)==0 ){ - return 1; - } - if( (f2 & MEM_Str)==0 ){ - return -1; - } - - assert( pMem1->enc==pMem2->enc ); - assert( pMem1->enc==SQLITE_UTF8 || - pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); - - /* The collation sequence must be defined at this point, even if - ** the user deletes the collation sequence after the vdbe program is - ** compiled (this was not always the case). - */ - assert( !pColl || pColl->xCmp ); - - if( pColl ){ - if( pMem1->enc==pColl->enc ){ - /* The strings are already in the correct encoding. Call the - ** comparison function directly */ - return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); - }else{ - const void *v1, *v2; - int n1, n2; - Mem c1; - Mem c2; - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); - sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); - v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); - n1 = v1==0 ? 0 : c1.n; - v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); - n2 = v2==0 ? 0 : c2.n; - rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); - sqlite3VdbeMemRelease(&c1); - sqlite3VdbeMemRelease(&c2); - return rc; - } - } - /* If a NULL pointer was passed as the collate function, fall through - ** to the blob case and use memcmp(). */ - } - - /* Both values must be blobs. Compare using memcmp(). */ - rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); - if( rc==0 ){ - rc = pMem1->n - pMem2->n; - } - return rc; -} - /* ** Move data out of a btree key or data field and into a Mem structure. ** The data or key is taken from the entry that pCur is currently pointing @@ -60541,22 +60882,22 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; + pMem->n = (int)amt; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ - pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; - pMem->enc = 0; - pMem->type = SQLITE_BLOB; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); } - pMem->z[amt] = 0; - pMem->z[amt+1] = 0; - if( rc!=SQLITE_OK ){ + if( rc==SQLITE_OK ){ + pMem->z[amt] = 0; + pMem->z[amt+1] = 0; + pMem->flags = MEM_Blob|MEM_Term; + pMem->n = (int)amt; + }else{ sqlite3VdbeMemRelease(pMem); } } - pMem->n = (int)amt; return rc; } @@ -60614,7 +60955,6 @@ SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){ Mem *p = sqlite3DbMallocZero(db, sizeof(*p)); if( p ){ p->flags = MEM_Null; - p->type = SQLITE_NULL; p->db = db; } return p; @@ -60660,11 +61000,9 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ if( pRec->pKeyInfo ){ assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol ); assert( pRec->pKeyInfo->enc==ENC(db) ); - pRec->flags = UNPACKED_PREFIX_MATCH; pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); for(i=0; iaMem[i].flags = MEM_Null; - pRec->aMem[i].type = SQLITE_NULL; pRec->aMem[i].db = db; } }else{ @@ -60737,7 +61075,6 @@ static int valueFromExpr( zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); if( zVal==0 ) goto no_mem; sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); - if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT; } if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); @@ -60755,9 +61092,9 @@ static int valueFromExpr( ){ sqlite3VdbeMemNumerify(pVal); if( pVal->u.i==SMALLEST_INT64 ){ - pVal->flags &= MEM_Int; + pVal->flags &= ~MEM_Int; pVal->flags |= MEM_Real; - pVal->r = (double)LARGEST_INT64; + pVal->r = (double)SMALLEST_INT64; }else{ pVal->u.i = -pVal->u.i; } @@ -60783,9 +61120,6 @@ static int valueFromExpr( } #endif - if( pVal ){ - sqlite3VdbeMemStoreType(pVal); - } *ppVal = pVal; return rc; @@ -60856,7 +61190,7 @@ static void recordFunc( }else{ aRet[0] = nSerial+1; sqlite3PutVarint(&aRet[1], iSerial); - sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format); + sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); sqlite3DbFree(db, aRet); } @@ -60949,7 +61283,6 @@ SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); } pVal->db = pParse->db; - sqlite3VdbeMemStoreType((Mem*)pVal); } } }else{ @@ -61041,7 +61374,8 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ /* ** Create a new virtual database engine. */ -SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){ +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ + sqlite3 *db = pParse->db; Vdbe *p; p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); if( p==0 ) return 0; @@ -61053,6 +61387,10 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){ p->pPrev = 0; db->pVdbe = p; p->magic = VDBE_MAGIC_INIT; + p->pParse = pParse; + assert( pParse->aLabel==0 ); + assert( pParse->nLabel==0 ); + assert( pParse->nOpAlloc==0 ); return p; } @@ -61108,13 +61446,14 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ ** unchanged (this is so that any opcodes already allocated can be ** correctly deallocated along with the rest of the Vdbe). */ -static int growOpArray(Vdbe *p){ +static int growOpArray(Vdbe *v){ VdbeOp *pNew; + Parse *p = v->pParse; int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); - pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op)); + pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); if( pNew ){ p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op); - p->aOp = pNew; + v->aOp = pNew; } return (pNew ? SQLITE_OK : SQLITE_NOMEM); } @@ -61153,7 +61492,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ i = p->nOp; assert( p->magic==VDBE_MAGIC_INIT ); assert( op>0 && op<0xff ); - if( p->nOpAlloc<=i ){ + if( p->pParse->nOpAlloc<=i ){ if( growOpArray(p) ){ return 1; } @@ -61172,6 +61511,15 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ #endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ + int jj, kk; + Parse *pParse = p->pParse; + for(jj=kk=0; jjaColCache + jj; + if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; + printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); + kk++; + } + if( kk ) printf("\n"); sqlite3VdbePrintOp(0, i, &p->aOp[i]); test_addop_breakpoint(); } @@ -61179,6 +61527,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ #ifdef VDBE_PROFILE pOp->cycles = 0; pOp->cnt = 0; +#endif +#ifdef SQLITE_VDBE_COVERAGE + pOp->iSrcLine = 0; #endif return i; } @@ -61255,9 +61606,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( ** ** Zero is returned if a malloc() fails. */ -SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){ +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){ + Parse *p = v->pParse; int i = p->nLabel++; - assert( p->magic==VDBE_MAGIC_INIT ); + assert( v->magic==VDBE_MAGIC_INIT ); if( (i & (i-1))==0 ){ p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, (i*2+1)*sizeof(p->aLabel[0])); @@ -61273,13 +61625,15 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){ ** be inserted. The parameter "x" must have been obtained from ** a prior call to sqlite3VdbeMakeLabel(). */ -SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){ +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ + Parse *p = v->pParse; int j = -1-x; - assert( p->magic==VDBE_MAGIC_INIT ); + assert( v->magic==VDBE_MAGIC_INIT ); assert( jnLabel ); if( j>=0 && p->aLabel ){ - p->aLabel[j] = p->nOp; + p->aLabel[j] = v->nOp; } + p->iFixedOp = v->nOp - 1; } /* @@ -61427,7 +61781,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; int nMaxArgs = *pMaxFuncArgs; Op *pOp; - int *aLabel = p->aLabel; + Parse *pParse = p->pParse; + int *aLabel = pParse->aLabel; p->readOnly = 1; p->bIsReader = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ @@ -61490,12 +61845,13 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ pOp->opflags = sqlite3OpcodeProperty[opcode]; if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ - assert( -1-pOp->p2nLabel ); + assert( -1-pOp->p2nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } } - sqlite3DbFree(p->db, p->aLabel); - p->aLabel = 0; + sqlite3DbFree(p->db, pParse->aLabel); + pParse->aLabel = 0; + pParse->nLabel = 0; *pMaxFuncArgs = nMaxArgs; assert( p->bIsReader!=0 || p->btreeMask==0 ); } @@ -61536,10 +61892,10 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg) ** Add a whole list of operations to the operation stack. Return the ** address of the first operation added. */ -SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){ int addr; assert( p->magic==VDBE_MAGIC_INIT ); - if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){ + if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){ return 0; } addr = p->nOp; @@ -61564,6 +61920,11 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp) #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOut->zComment = 0; #endif +#ifdef SQLITE_VDBE_COVERAGE + pOut->iSrcLine = iLineno+i; +#else + (void)iLineno; +#endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); @@ -61626,7 +61987,8 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ ** the address of the next instruction to be coded. */ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ - if( ALWAYS(addr>=0) ) sqlite3VdbeChangeP2(p, addr, p->nOp); + sqlite3VdbeChangeP2(p, addr, p->nOp); + p->pParse->iFixedOp = p->nOp - 1; } @@ -61728,6 +62090,18 @@ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ } } +/* +** Remove the last opcode inserted +*/ +SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ + if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ + sqlite3VdbeChangeToNoop(p, p->nOp-1); + return 1; + }else{ + return 0; + } +} + /* ** Change the value of the P4 operand for a specific instruction. ** This routine is useful when a large program is loaded from a @@ -61839,6 +62213,15 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ } #endif /* NDEBUG */ +#ifdef SQLITE_VDBE_COVERAGE +/* +** Set the value if the iSrcLine field for the previously coded instruction. +*/ +SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ + sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine; +} +#endif /* SQLITE_VDBE_COVERAGE */ + /* ** Return the opcode for a given address. If the address is -1, then ** return the most recently inserted opcode. @@ -61851,14 +62234,6 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ ** this routine is a valid pointer. But because the dummy.opcode is 0, ** dummy will never be written to. This is verified by code inspection and ** by running with Valgrind. -** -** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called -** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE, -** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as -** a new VDBE is created. So we are free to set addr to p->nOp-1 without -** having to double-check to make sure that the result is non-negative. But -** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to -** check the value of p->nOp-1 before continuing. */ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ /* C89 specifies that the constant "dummy" will be initialized to all @@ -61866,9 +62241,6 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */ assert( p->magic==VDBE_MAGIC_INIT ); if( addr<0 ){ -#ifdef SQLITE_OMIT_TRACE - if( p->nOp==0 ) return (VdbeOp*)&dummy; -#endif addr = p->nOp - 1; } assert( (addr>=0 && addrnOp) || p->db->mallocFailed ); @@ -61893,7 +62265,17 @@ static int translateP(char c, const Op *pOp){ } /* -** Compute a string for the "comment" field of a VDBE opcode listing +** Compute a string for the "comment" field of a VDBE opcode listing. +** +** The Synopsis: field in comments in the vdbe.c source file gets converted +** to an extra string that is appended to the sqlite3OpcodeName(). In the +** absence of other comments, this synopsis becomes the comment on the opcode. +** Some translation occurs: +** +** "PX" -> "r[X]" +** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1 +** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0 +** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x */ static int displayComment( const Op *pOp, /* The opcode to be commented */ @@ -61927,7 +62309,13 @@ static int displayComment( ii += 3; jj += sqlite3Strlen30(zTemp+jj); v2 = translateP(zSynopsis[ii], pOp); - if( v2>1 ) sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1); + if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){ + ii += 2; + v2++; + } + if( v2>1 ){ + sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1); + } }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){ ii += 4; } @@ -62157,8 +62545,11 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS displayComment(pOp, zP4, zCom, sizeof(zCom)); #else - zCom[0] = 0 + zCom[0] = 0; #endif + /* NB: The sqlite3OpcodeName() function is implemented by code created + ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the + ** information from the vdbe.c source text */ fprintf(pOut, zFormat1, pc, sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, zCom @@ -62183,6 +62574,7 @@ static void releaseMemArray(Mem *p, int N){ } for(pEnd=&p[N]; pflags & MEM_Agg ); + testcase( p->flags & MEM_Dyn ); + testcase( p->flags & MEM_Frame ); + testcase( p->flags & MEM_RowSet ); if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); }else if( p->zMalloc ){ @@ -62203,7 +62599,7 @@ static void releaseMemArray(Mem *p, int N){ p->zMalloc = 0; } - p->flags = MEM_Invalid; + p->flags = MEM_Undefined; } db->mallocFailed = malloc_failed; } @@ -62325,7 +62721,6 @@ SQLITE_PRIVATE int sqlite3VdbeList( } if( p->explain==1 ){ pMem->flags = MEM_Int; - pMem->type = SQLITE_INTEGER; pMem->u.i = i; /* Program counter */ pMem++; @@ -62333,7 +62728,6 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ assert( pMem->z!=0 ); pMem->n = sqlite3Strlen30(pMem->z); - pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; pMem++; @@ -62359,24 +62753,21 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem->flags = MEM_Int; pMem->u.i = pOp->p1; /* P1 */ - pMem->type = SQLITE_INTEGER; pMem++; pMem->flags = MEM_Int; pMem->u.i = pOp->p2; /* P2 */ - pMem->type = SQLITE_INTEGER; pMem++; pMem->flags = MEM_Int; pMem->u.i = pOp->p3; /* P3 */ - pMem->type = SQLITE_INTEGER; pMem++; if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */ assert( p->db->mallocFailed ); return SQLITE_ERROR; } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->flags = MEM_Str|MEM_Term; zP4 = displayP4(pOp, pMem->z, 32); if( zP4!=pMem->z ){ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); @@ -62385,7 +62776,6 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; } - pMem->type = SQLITE_TEXT; pMem++; if( p->explain==1 ){ @@ -62393,10 +62783,9 @@ SQLITE_PRIVATE int sqlite3VdbeList( assert( p->db->mallocFailed ); return SQLITE_ERROR; } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->flags = MEM_Str|MEM_Term; pMem->n = 2; sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ - pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; pMem++; @@ -62405,13 +62794,11 @@ SQLITE_PRIVATE int sqlite3VdbeList( assert( p->db->mallocFailed ); return SQLITE_ERROR; } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->flags = MEM_Str|MEM_Term; pMem->n = displayComment(pOp, zP4, pMem->z, 500); - pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; #else pMem->flags = MEM_Null; /* Comment */ - pMem->type = SQLITE_NULL; #endif } @@ -62434,7 +62821,7 @@ SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){ z = p->zSql; }else if( p->nOp>=1 ){ const VdbeOp *pOp = &p->aOp[0]; - if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ + if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){ z = pOp->p4.z; while( sqlite3Isspace(*z) ) z++; } @@ -62453,7 +62840,7 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ if( sqlite3IoTrace==0 ) return; if( nOp<1 ) return; pOp = &p->aOp[0]; - if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ + if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){ int i, j; char z[1000]; sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z); @@ -62590,6 +62977,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( assert( p->nOp>0 ); assert( pParse!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); + assert( pParse==p->pParse ); db = p->db; assert( db->mallocFailed==0 ); nVar = pParse->nVar; @@ -62613,8 +63001,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( /* Allocate space for memory registers, SQL variables, VDBE cursors and ** an array to marshal SQL function arguments in. */ - zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */ - zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */ + zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */ + zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */ resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); @@ -62670,7 +63058,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( p->aMem--; /* aMem[] goes from 1..nMem */ p->nMem = nMem; /* not from 0..nMem-1 */ for(n=1; n<=nMem; n++){ - p->aMem[n].flags = MEM_Invalid; + p->aMem[n].flags = MEM_Undefined; p->aMem[n].db = db; } } @@ -62782,7 +63170,7 @@ static void Cleanup(Vdbe *p){ int i; if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 ); if( p->aMem ){ - for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid ); + for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); } #endif @@ -63441,6 +63829,7 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ if( p->zErrMsg ){ u8 mallocFailed = db->mallocFailed; sqlite3BeginBenignMalloc(); + if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); sqlite3EndBenignMalloc(); db->mallocFailed = mallocFailed; @@ -63509,8 +63898,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ - sqlite3Error(db, p->rc, 0); - sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); + sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } @@ -63531,12 +63919,24 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ fprintf(out, "%02x", p->aOp[i].opcode); } fprintf(out, "\n"); + if( p->zSql ){ + char c, pc = 0; + fprintf(out, "-- "); + for(i=0; (c = p->zSql[i])!=0; i++){ + if( pc=='\n' ) fprintf(out, "-- "); + putc(c, out); + pc = c; + } + if( pc!='\n' ) fprintf(out, "\n"); + } for(i=0; inOp; i++){ - fprintf(out, "%6d %10lld %8lld ", + char zHdr[100]; + sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", p->aOp[i].cnt, p->aOp[i].cycles, p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 ); + fprintf(out, "%s", zHdr); sqlite3VdbePrintOp(out, i, &p->aOp[i]); } fclose(out); @@ -63583,8 +63983,9 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){ while( *pp ){ AuxData *pAux = *pp; if( (iOp<0) - || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<iArg)))) + || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg)))) ){ + testcase( pAux->iArg==31 ); if( pAux->xDelete ){ pAux->xDelete(pAux->pAux); } @@ -63617,7 +64018,6 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ } for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); - sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); @@ -63848,21 +64248,15 @@ static u64 floatSwap(u64 in){ ** buf. It is assumed that the caller has allocated sufficient space. ** Return the number of bytes written. ** -** nBuf is the amount of space left in buf[]. nBuf must always be -** large enough to hold the entire field. Except, if the field is -** a blob with a zero-filled tail, then buf[] might be just the right -** size to hold everything except for the zero-filled tail. If buf[] -** is only big enough to hold the non-zero prefix, then only write that -** prefix into buf[]. But if buf[] is large enough to hold both the -** prefix and the tail then write the prefix and set the tail to all -** zeros. +** nBuf is the amount of space left in buf[]. The caller is responsible +** for allocating enough space to buf[] to hold the entire field, exclusive +** of the pMem->u.nZero bytes for a MEM_Zero value. ** ** Return the number of bytes actually written into buf[]. The number ** of bytes in the zero-filled tail is included in the return value only ** if those bytes were zeroed in buf[]. */ -SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ - u32 serial_type = sqlite3VdbeSerialType(pMem, file_format); +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ u32 len; /* Integer and Real */ @@ -63877,7 +64271,6 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); - assert( len<=(u32)nBuf ); while( i-- ){ buf[i] = (u8)(v&0xFF); v >>= 8; @@ -63889,17 +64282,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f if( serial_type>=12 ){ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) == (int)sqlite3VdbeSerialTypeLen(serial_type) ); - assert( pMem->n<=nBuf ); len = pMem->n; memcpy(buf, pMem->z, len); - if( pMem->flags & MEM_Zero ){ - len += pMem->u.nZero; - assert( nBuf>=0 ); - if( len > (u32)nBuf ){ - len = (u32)nBuf; - } - memset(&buf[pMem->n], 0, len-pMem->n); - } return len; } @@ -63907,6 +64291,14 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f return 0; } +/* Input "x" is a sequence of unsigned characters that represent a +** big-endian integer. Return the equivalent native integer +*/ +#define ONE_BYTE_INT(x) ((i8)(x)[0]) +#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) +#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) +#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) + /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. @@ -63916,6 +64308,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ + u64 x; + u32 y; switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ @@ -63924,37 +64318,38 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( break; } case 1: { /* 1-byte signed integer */ - pMem->u.i = (signed char)buf[0]; + pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 1; } case 2: { /* 2-byte signed integer */ - pMem->u.i = (((signed char)buf[0])<<8) | buf[1]; + pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 2; } case 3: { /* 3-byte signed integer */ - pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2]; + pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 3; } case 4: { /* 4-byte signed integer */ - pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; + y = FOUR_BYTE_UINT(buf); + pMem->u.i = (i64)*(int*)&y; pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 4; } case 5: { /* 6-byte signed integer */ - u64 x = (((signed char)buf[0])<<8) | buf[1]; - u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]; - x = (x<<32) | y; - pMem->u.i = *(i64*)&x; + pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 6; } case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ - u64 x; - u32 y; #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) /* Verify that integers and floating point values use the same ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is @@ -63967,13 +64362,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( swapMixedEndianFloat(t2); assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); #endif - - x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; - y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7]; + x = FOUR_BYTE_UINT(buf); + y = FOUR_BYTE_UINT(buf+4); x = (x<<32) | y; if( serial_type==6 ){ pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); }else{ assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); swapMixedEndianFloat(x); @@ -64065,7 +64460,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( u32 szHdr; Mem *pMem = p->aMem; - p->flags = 0; + p->default_rc = 0; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); idx = getVarint32(aKey, szHdr); d = szHdr; @@ -64086,26 +64481,18 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( p->nField = u; } +#if SQLITE_DEBUG /* -** This function compares the two table rows or index records -** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero -** or positive integer if key1 is less than, equal to or -** greater than key2. The {nKey1, pKey1} key must be a blob -** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 -** key must be a parsed key such as obtained from -** sqlite3VdbeParseRecord. -** -** Key1 and Key2 do not have to contain the same number of fields. -** The key with fewer fields is usually compares less than the -** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set -** and the common prefixes are equal, then key1 is less than key2. -** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are -** equal, then the keys are considered to be equal and -** the parts beyond the common prefix are ignored. +** This function compares two index or table record keys in the same way +** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), +** this function deserializes and compares values using the +** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used +** in assert() statements to ensure that the optimized code in +** sqlite3VdbeRecordCompare() returns results with these two primitives. */ -SQLITE_PRIVATE int sqlite3VdbeRecordCompare( +static int vdbeRecordCompareDebug( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ + const UnpackedRecord *pPKey2 /* Right key */ ){ u32 d1; /* Offset into aKey[] of next data element */ u32 idx1; /* Offset into aKey[] of next header element */ @@ -64179,24 +64566,576 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare( assert( mem1.zMalloc==0 ); /* rc==0 here means that one of the keys ran out of fields and - ** all the fields up to that point were equal. If the UNPACKED_INCRKEY - ** flag is set, then break the tie by treating key2 as larger. - ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes - ** are considered to be equal. Otherwise, the longer key is the - ** larger. As it happens, the pPKey2 will always be the longer - ** if there is a difference. - */ - assert( rc==0 ); - if( pPKey2->flags & UNPACKED_INCRKEY ){ - rc = -1; - }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){ - /* Leave rc==0 */ - }else if( idx1default_rc; +} +#endif + +/* +** Both *pMem1 and *pMem2 contain string values. Compare the two values +** using the collation sequence pColl. As usual, return a negative , zero +** or positive value if *pMem1 is less than, equal to or greater than +** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". +*/ +static int vdbeCompareMemString( + const Mem *pMem1, + const Mem *pMem2, + const CollSeq *pColl +){ + if( pMem1->enc==pColl->enc ){ + /* The strings are already in the correct encoding. Call the + ** comparison function directly */ + return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); + }else{ + int rc; + const void *v1, *v2; + int n1, n2; + Mem c1; + Mem c2; + memset(&c1, 0, sizeof(c1)); + memset(&c2, 0, sizeof(c2)); + sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); + sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); + v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); + n1 = v1==0 ? 0 : c1.n; + v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); + n2 = v2==0 ? 0 : c2.n; + rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); + sqlite3VdbeMemRelease(&c1); + sqlite3VdbeMemRelease(&c2); + return rc; } - return rc; } + +/* +** Compare the values contained by the two memory cells, returning +** negative, zero or positive if pMem1 is less than, equal to, or greater +** than pMem2. Sorting order is NULL's first, followed by numbers (integers +** and reals) sorted numerically, followed by text ordered by the collating +** sequence pColl and finally blob's ordered by memcmp(). +** +** Two NULL values are considered equal by this function. +*/ +SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ + int rc; + int f1, f2; + int combined_flags; + + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; + assert( (combined_flags & MEM_RowSet)==0 ); + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. + */ + if( combined_flags&MEM_Null ){ + return (f2&MEM_Null) - (f1&MEM_Null); + } + + /* If one value is a number and the other is not, the number is less. + ** If both are numbers, compare as reals if one is a real, or as integers + ** if both values are integers. + */ + if( combined_flags&(MEM_Int|MEM_Real) ){ + double r1, r2; + if( (f1 & f2 & MEM_Int)!=0 ){ + if( pMem1->u.i < pMem2->u.i ) return -1; + if( pMem1->u.i > pMem2->u.i ) return 1; + return 0; + } + if( (f1&MEM_Real)!=0 ){ + r1 = pMem1->r; + }else if( (f1&MEM_Int)!=0 ){ + r1 = (double)pMem1->u.i; + }else{ + return 1; + } + if( (f2&MEM_Real)!=0 ){ + r2 = pMem2->r; + }else if( (f2&MEM_Int)!=0 ){ + r2 = (double)pMem2->u.i; + }else{ + return -1; + } + if( r1r2 ) return 1; + return 0; + } + + /* If one value is a string and the other is a blob, the string is less. + ** If both are strings, compare using the collating functions. + */ + if( combined_flags&MEM_Str ){ + if( (f1 & MEM_Str)==0 ){ + return 1; + } + if( (f2 & MEM_Str)==0 ){ + return -1; + } + + assert( pMem1->enc==pMem2->enc ); + assert( pMem1->enc==SQLITE_UTF8 || + pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); + + /* The collation sequence must be defined at this point, even if + ** the user deletes the collation sequence after the vdbe program is + ** compiled (this was not always the case). + */ + assert( !pColl || pColl->xCmp ); + + if( pColl ){ + return vdbeCompareMemString(pMem1, pMem2, pColl); + } + /* If a NULL pointer was passed as the collate function, fall through + ** to the blob case and use memcmp(). */ + } + + /* Both values must be blobs. Compare using memcmp(). */ + rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); + if( rc==0 ){ + rc = pMem1->n - pMem2->n; + } + return rc; +} + + +/* +** The first argument passed to this function is a serial-type that +** corresponds to an integer - all values between 1 and 9 inclusive +** except 7. The second points to a buffer containing an integer value +** serialized according to serial_type. This function deserializes +** and returns the value. +*/ +static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ + u32 y; + assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); + switch( serial_type ){ + case 0: + case 1: + testcase( aKey[0]&0x80 ); + return ONE_BYTE_INT(aKey); + case 2: + testcase( aKey[0]&0x80 ); + return TWO_BYTE_INT(aKey); + case 3: + testcase( aKey[0]&0x80 ); + return THREE_BYTE_INT(aKey); + case 4: { + testcase( aKey[0]&0x80 ); + y = FOUR_BYTE_UINT(aKey); + return (i64)*(int*)&y; + } + case 5: { + testcase( aKey[0]&0x80 ); + return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); + } + case 6: { + u64 x = FOUR_BYTE_UINT(aKey); + testcase( aKey[0]&0x80 ); + x = (x<<32) | FOUR_BYTE_UINT(aKey+4); + return (i64)*(i64*)&x; + } + } + + return (serial_type - 8); +} + +/* +** This function compares the two table rows or index records +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero +** or positive integer if key1 is less than, equal to or +** greater than key2. The {nKey1, pKey1} key must be a blob +** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 +** key must be a parsed key such as obtained from +** sqlite3VdbeParseRecord. +** +** If argument bSkip is non-zero, it is assumed that the caller has already +** determined that the first fields of the keys are equal. +** +** Key1 and Key2 do not have to contain the same number of fields. If all +** fields that appear in both keys are equal, then pPKey2->default_rc is +** returned. +*/ +SQLITE_PRIVATE int sqlite3VdbeRecordCompare( + int nKey1, const void *pKey1, /* Left key */ + const UnpackedRecord *pPKey2, /* Right key */ + int bSkip /* If true, skip the first field */ +){ + u32 d1; /* Offset into aKey[] of next data element */ + int i; /* Index of next field to compare */ + u32 szHdr1; /* Size of record header in bytes */ + u32 idx1; /* Offset of first type in header */ + int rc = 0; /* Return value */ + Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ + KeyInfo *pKeyInfo = pPKey2->pKeyInfo; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + Mem mem1; + + /* If bSkip is true, then the caller has already determined that the first + ** two elements in the keys are equal. Fix the various stack variables so + ** that this routine begins comparing at the second field. */ + if( bSkip ){ + u32 s1; + idx1 = 1 + getVarint32(&aKey1[1], s1); + szHdr1 = aKey1[0]; + d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1); + i = 1; + pRhs++; + }else{ + idx1 = getVarint32(aKey1, szHdr1); + d1 = szHdr1; + i = 0; + } + + VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ + assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField + || CORRUPT_DB ); + assert( pPKey2->pKeyInfo->aSortOrder!=0 ); + assert( pPKey2->pKeyInfo->nField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + u32 serial_type; + + /* RHS is an integer */ + if( pRhs->flags & MEM_Int ){ + serial_type = aKey1[idx1]; + testcase( serial_type==12 ); + if( serial_type>=12 ){ + rc = +1; + }else if( serial_type==0 ){ + rc = -1; + }else if( serial_type==7 ){ + double rhs = (double)pRhs->u.i; + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + if( mem1.rrhs ){ + rc = +1; + } + }else{ + i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); + i64 rhs = pRhs->u.i; + if( lhsrhs ){ + rc = +1; + } + } + } + + /* RHS is real */ + else if( pRhs->flags & MEM_Real ){ + serial_type = aKey1[idx1]; + if( serial_type>=12 ){ + rc = +1; + }else if( serial_type==0 ){ + rc = -1; + }else{ + double rhs = pRhs->r; + double lhs; + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + if( serial_type==7 ){ + lhs = mem1.r; + }else{ + lhs = (double)mem1.u.i; + } + if( lhsrhs ){ + rc = +1; + } + } + } + + /* RHS is a string */ + else if( pRhs->flags & MEM_Str ){ + getVarint32(&aKey1[idx1], serial_type); + testcase( serial_type==12 ); + if( serial_type<12 ){ + rc = -1; + }else if( !(serial_type & 0x01) ){ + rc = +1; + }else{ + mem1.n = (serial_type - 12) / 2; + testcase( (d1+mem1.n)==(unsigned)nKey1 ); + testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); + if( (d1+mem1.n) > (unsigned)nKey1 ){ + rc = 1; /* Corruption */ + }else if( pKeyInfo->aColl[i] ){ + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + mem1.flags = MEM_Str; + mem1.z = (char*)&aKey1[d1]; + rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]); + }else{ + int nCmp = MIN(mem1.n, pRhs->n); + rc = memcmp(&aKey1[d1], pRhs->z, nCmp); + if( rc==0 ) rc = mem1.n - pRhs->n; + } + } + } + + /* RHS is a blob */ + else if( pRhs->flags & MEM_Blob ){ + getVarint32(&aKey1[idx1], serial_type); + testcase( serial_type==12 ); + if( serial_type<12 || (serial_type & 0x01) ){ + rc = -1; + }else{ + int nStr = (serial_type - 12) / 2; + testcase( (d1+nStr)==(unsigned)nKey1 ); + testcase( (d1+nStr+1)==(unsigned)nKey1 ); + if( (d1+nStr) > (unsigned)nKey1 ){ + rc = 1; /* Corruption */ + }else{ + int nCmp = MIN(nStr, pRhs->n); + rc = memcmp(&aKey1[d1], pRhs->z, nCmp); + if( rc==0 ) rc = nStr - pRhs->n; + } + } + } + + /* RHS is null */ + else{ + serial_type = aKey1[idx1]; + rc = (serial_type!=0); + } + + if( rc!=0 ){ + if( pKeyInfo->aSortOrder[i] ){ + rc = -rc; + } + assert( CORRUPT_DB + || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) + || pKeyInfo->db->mallocFailed + ); + assert( mem1.zMalloc==0 ); /* See comment below */ + return rc; + } + + i++; + pRhs++; + d1 += sqlite3VdbeSerialTypeLen(serial_type); + idx1 += sqlite3VarintLen(serial_type); + }while( idx1<(unsigned)szHdr1 && inField && d1<=(unsigned)nKey1 ); + + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ + assert( mem1.zMalloc==0 ); + + /* rc==0 here means that one or both of the keys ran out of fields and + ** all the fields up to that point were equal. Return the the default_rc + ** value. */ + assert( CORRUPT_DB + || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2) + ); + return pPKey2->default_rc; +} + +/* +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is an integer, and (b) the +** size-of-header varint at the start of (pKey1/nKey1) fits in a single +** byte (i.e. is less than 128). +*/ +static int vdbeRecordCompareInt( + int nKey1, const void *pKey1, /* Left key */ + const UnpackedRecord *pPKey2, /* Right key */ + int bSkip /* Ignored */ +){ + const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; + int serial_type = ((const u8*)pKey1)[1]; + int res; + u32 y; + u64 x; + i64 v = pPKey2->aMem[0].u.i; + i64 lhs; + UNUSED_PARAMETER(bSkip); + + assert( bSkip==0 ); + switch( serial_type ){ + case 1: { /* 1-byte signed integer */ + lhs = ONE_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 2: { /* 2-byte signed integer */ + lhs = TWO_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 3: { /* 3-byte signed integer */ + lhs = THREE_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 4: { /* 4-byte signed integer */ + y = FOUR_BYTE_UINT(aKey); + lhs = (i64)*(int*)&y; + testcase( lhs<0 ); + break; + } + case 5: { /* 6-byte signed integer */ + lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); + testcase( lhs<0 ); + break; + } + case 6: { /* 8-byte signed integer */ + x = FOUR_BYTE_UINT(aKey); + x = (x<<32) | FOUR_BYTE_UINT(aKey+4); + lhs = *(i64*)&x; + testcase( lhs<0 ); + break; + } + case 8: + lhs = 0; + break; + case 9: + lhs = 1; + break; + + /* This case could be removed without changing the results of running + ** this code. Including it causes gcc to generate a faster switch + ** statement (since the range of switch targets now starts at zero and + ** is contiguous) but does not cause any duplicate code to be generated + ** (as gcc is clever enough to combine the two like cases). Other + ** compilers might be similar. */ + case 0: case 7: + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0); + + default: + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0); + } + + if( v>lhs ){ + res = pPKey2->r1; + }else if( vr2; + }else if( pPKey2->nField>1 ){ + /* The first fields of the two keys are equal. Compare the trailing + ** fields. */ + res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1); + }else{ + /* The first fields of the two keys are equal and there are no trailing + ** fields. Return pPKey2->default_rc in this case. */ + res = pPKey2->default_rc; + } + + assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) + || CORRUPT_DB + ); + return res; +} + +/* +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is a string, that (b) the first field +** uses the collation sequence BINARY and (c) that the size-of-header varint +** at the start of (pKey1/nKey1) fits in a single byte. +*/ +static int vdbeRecordCompareString( + int nKey1, const void *pKey1, /* Left key */ + const UnpackedRecord *pPKey2, /* Right key */ + int bSkip +){ + const u8 *aKey1 = (const u8*)pKey1; + int serial_type; + int res; + UNUSED_PARAMETER(bSkip); + + assert( bSkip==0 ); + getVarint32(&aKey1[1], serial_type); + + if( serial_type<12 ){ + res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ + }else if( !(serial_type & 0x01) ){ + res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ + }else{ + int nCmp; + int nStr; + int szHdr = aKey1[0]; + + nStr = (serial_type-12) / 2; + if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ + nCmp = MIN( pPKey2->aMem[0].n, nStr ); + res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); + + if( res==0 ){ + res = nStr - pPKey2->aMem[0].n; + if( res==0 ){ + if( pPKey2->nField>1 ){ + res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1); + }else{ + res = pPKey2->default_rc; + } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; + } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; + } + } + + assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) + || CORRUPT_DB + ); + return res; +} + +/* +** Return a pointer to an sqlite3VdbeRecordCompare() compatible function +** suitable for comparing serialized records to the unpacked record passed +** as the only argument. +*/ +SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ + /* varintRecordCompareInt() and varintRecordCompareString() both assume + ** that the size-of-header varint that occurs at the start of each record + ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt() + ** also assumes that it is safe to overread a buffer by at least the + ** maximum possible legal header size plus 8 bytes. Because there is + ** guaranteed to be at least 74 (but not 136) bytes of padding following each + ** buffer passed to varintRecordCompareInt() this makes it convenient to + ** limit the size of the header to 64 bytes in cases where the first field + ** is an integer. + ** + ** The easiest way to enforce this limit is to consider only records with + ** 13 fields or less. If the first field is an integer, the maximum legal + ** header size is (12*5 + 1 + 1) bytes. */ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ + int flags = p->aMem[0].flags; + if( p->pKeyInfo->aSortOrder[0] ){ + p->r1 = 1; + p->r2 = -1; + }else{ + p->r1 = -1; + p->r2 = 1; + } + if( (flags & MEM_Int) ){ + return vdbeRecordCompareInt; + } + testcase( flags & MEM_Real ); + testcase( flags & MEM_Null ); + testcase( flags & MEM_Blob ); + if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ + assert( flags & MEM_Str ); + return vdbeRecordCompareString; + } + } + + return sqlite3VdbeRecordCompare; +} /* ** pCur points at an index entry created using the OP_MakeRecord opcode. @@ -64287,9 +65226,9 @@ idx_rowid_corruption: ** of the keys prior to the final rowid, not the entire key. */ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( - VdbeCursor *pC, /* The cursor to compare against */ - UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */ - int *res /* Write the comparison result here */ + VdbeCursor *pC, /* The cursor to compare against */ + const UnpackedRecord *pUnpacked, /* Unpacked version of key */ + int *res /* Write the comparison result here */ ){ i64 nCellKey = 0; int rc; @@ -64299,7 +65238,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( assert( sqlite3BtreeCursorIsValid(pCur) ); VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ - /* nCellKey will always be between 0 and 0xffffffff because of the say + /* nCellKey will always be between 0 and 0xffffffff because of the way ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; @@ -64310,8 +65249,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( if( rc ){ return rc; } - assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH ); - *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); + *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0); sqlite3VdbeMemRelease(&m); return SQLITE_OK; } @@ -64375,7 +65313,6 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff if( pRet ){ sqlite3VdbeMemCopy((Mem *)pRet, pMem); sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8); - sqlite3VdbeMemStoreType((Mem *)pRet); } return pRet; } @@ -64549,7 +65486,6 @@ SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ sqlite3VdbeMemExpandBlob(p); - p->flags &= ~MEM_Str; p->flags |= MEM_Blob; return p->n ? p->z : 0; }else{ @@ -64586,7 +65522,41 @@ SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ - return pVal->type; + static const u8 aType[] = { + SQLITE_BLOB, /* 0x00 */ + SQLITE_NULL, /* 0x01 */ + SQLITE_TEXT, /* 0x02 */ + SQLITE_NULL, /* 0x03 */ + SQLITE_INTEGER, /* 0x04 */ + SQLITE_NULL, /* 0x05 */ + SQLITE_INTEGER, /* 0x06 */ + SQLITE_NULL, /* 0x07 */ + SQLITE_FLOAT, /* 0x08 */ + SQLITE_NULL, /* 0x09 */ + SQLITE_FLOAT, /* 0x0a */ + SQLITE_NULL, /* 0x0b */ + SQLITE_INTEGER, /* 0x0c */ + SQLITE_NULL, /* 0x0d */ + SQLITE_INTEGER, /* 0x0e */ + SQLITE_NULL, /* 0x0f */ + SQLITE_BLOB, /* 0x10 */ + SQLITE_NULL, /* 0x11 */ + SQLITE_TEXT, /* 0x12 */ + SQLITE_NULL, /* 0x13 */ + SQLITE_INTEGER, /* 0x14 */ + SQLITE_NULL, /* 0x15 */ + SQLITE_INTEGER, /* 0x16 */ + SQLITE_NULL, /* 0x17 */ + SQLITE_FLOAT, /* 0x18 */ + SQLITE_NULL, /* 0x19 */ + SQLITE_FLOAT, /* 0x1a */ + SQLITE_NULL, /* 0x1b */ + SQLITE_INTEGER, /* 0x1c */ + SQLITE_NULL, /* 0x1d */ + SQLITE_INTEGER, /* 0x1e */ + SQLITE_NULL, /* 0x1f */ + }; + return aType[pVal->flags&MEM_AffMask]; } /**************************** sqlite3_result_ ******************************* @@ -64900,7 +65870,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ v->doingRerun = 1; assert( v->expired==0 ); } - if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ + if( rc2!=SQLITE_OK ){ /* This case occurs after failing to recompile an sql statement. ** The error message from the SQL compiler has already been loaded ** into the database handle. This block copies the error message @@ -64910,6 +65880,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ ** sqlite3_errmsg() and sqlite3_errcode(). */ const char *zErr = (const char *)sqlite3_value_text(db->pErr); + assert( zErr!=0 || db->mallocFailed ); sqlite3DbFree(db, v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); @@ -65106,6 +66077,30 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ return pVm->nResColumn; } +/* +** Return a pointer to static memory containing an SQL NULL value. +*/ +static const Mem *columnNullValue(void){ + /* Even though the Mem structure contains an element + ** of type i64, on certain architectures (x86) with certain compiler + ** switches (-Os), gcc may align this Mem object on a 4-byte boundary + ** instead of an 8-byte one. This all works fine, except that when + ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s + ** that a Mem structure is located on an 8-byte boundary. To prevent + ** these assert()s from failing, when building with SQLITE_DEBUG defined + ** using gcc, we force nullMem to be 8-byte aligned using the magical + ** __attribute__((aligned(8))) macro. */ + static const Mem nullMem +#if defined(SQLITE_DEBUG) && defined(__GNUC__) + __attribute__((aligned(8))) +#endif + = {0, "", (double)0, {0}, 0, MEM_Null, 0, +#ifdef SQLITE_DEBUG + 0, 0, /* pScopyFrom, pFiller */ +#endif + 0, 0 }; + return &nullMem; +} /* ** Check to see if column iCol of the given statement is valid. If @@ -65122,32 +66117,11 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ sqlite3_mutex_enter(pVm->db->mutex); pOut = &pVm->pResultSet[i]; }else{ - /* If the value passed as the second argument is out of range, return - ** a pointer to the following static Mem object which contains the - ** value SQL NULL. Even though the Mem structure contains an element - ** of type i64, on certain architectures (x86) with certain compiler - ** switches (-Os), gcc may align this Mem object on a 4-byte boundary - ** instead of an 8-byte one. This all works fine, except that when - ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s - ** that a Mem structure is located on an 8-byte boundary. To prevent - ** these assert()s from failing, when building with SQLITE_DEBUG defined - ** using gcc, we force nullMem to be 8-byte aligned using the magical - ** __attribute__((aligned(8))) macro. */ - static const Mem nullMem -#if defined(SQLITE_DEBUG) && defined(__GNUC__) - __attribute__((aligned(8))) -#endif - = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0, -#ifdef SQLITE_DEBUG - 0, 0, /* pScopyFrom, pFiller */ -#endif - 0, 0 }; - if( pVm && ALWAYS(pVm->db) ){ sqlite3_mutex_enter(pVm->db->mutex); sqlite3Error(pVm->db, SQLITE_RANGE, 0); } - pOut = (Mem*)&nullMem; + pOut = (Mem*)columnNullValue(); } return pOut; } @@ -65544,7 +66518,7 @@ SQLITE_API int sqlite3_bind_text16( #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; - switch( pValue->type ){ + switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { rc = sqlite3_bind_int64(pStmt, i, pValue->u.i); break; @@ -65825,6 +66799,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); sqlite3StrAccumAppend(&out, "-- ", 3); + assert( (zRawSql - zStart) > 0 ); sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } }else{ @@ -65857,9 +66832,9 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( if( pVar->flags & MEM_Null ){ sqlite3StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & MEM_Int ){ - sqlite3XPrintf(&out, "%lld", pVar->u.i); + sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, "%!.15g", pVar->r); + sqlite3XPrintf(&out, 0, "%!.15g", pVar->r); }else if( pVar->flags & MEM_Str ){ int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16 @@ -65880,15 +66855,17 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } } #endif - sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); + sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); #ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOutn ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); + if( nOutn ){ + sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); + } #endif #ifndef SQLITE_OMIT_UTF16 if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); #endif }else if( pVar->flags & MEM_Zero ){ - sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); + sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); }else{ int nOut; /* Number of bytes of the blob to include in output */ assert( pVar->flags & MEM_Blob ); @@ -65898,11 +66875,13 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; #endif for(i=0; iz[i]&0xff); + sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff); } sqlite3StrAccumAppend(&out, "'", 1); #ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOutn ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); + if( nOutn ){ + sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); + } #endif } } @@ -65961,7 +66940,7 @@ SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){ sqlite3AppendSpace(&p->str, p->aIndent[n-1]); } va_start(ap, zFormat); - sqlite3VXPrintf(&p->str, 1, zFormat, ap); + sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap); va_end(ap); } } @@ -66040,33 +67019,8 @@ SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** The code in this file implements execution method of the -** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c") -** handles housekeeping details such as creating and deleting -** VDBE instances. This file is solely interested in executing -** the VDBE program. -** -** In the external interface, an "sqlite3_stmt*" is an opaque pointer -** to a VDBE. -** -** The SQL parser generates a program which is then executed by -** the VDBE to do the work of the SQL statement. VDBE programs are -** similar in form to assembly language. The program consists of -** a linear sequence of operations. Each operation has an opcode -** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4 -** is a null-terminated string. Operand P5 is an unsigned character. -** Few opcodes use all 5 operands. -** -** Computation results are stored on a set of registers numbered beginning -** with 1 and going up to Vdbe.nMem. Each register can store -** either an integer, a null-terminated string, a floating point -** number, or the SQL "NULL" value. An implicit conversion from one -** type to the other occurs as necessary. -** -** Most of the code in this file is taken up by the sqlite3VdbeExec() -** function which does the work of interpreting a VDBE program. -** But other routines are also provided to help in building up -** a program instruction by instruction. +** The code in this file implements the function that runs the +** bytecode of a prepared statement. ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting @@ -66078,7 +67032,11 @@ SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){ /* ** Invoke this macro on memory cells just prior to changing the ** value of the cell. This macro verifies that shallow copies are -** not misused. +** not misused. A shallow copy of a string or blob just copies a +** pointer to the string or blob, not the content. If the original +** is changed while the copy is still in use, the string or blob might +** be changed out from under the copy. This macro verifies that nothing +** like that ever happens. */ #ifdef SQLITE_DEBUG # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) @@ -66137,7 +67095,7 @@ static void updateMaxBlobsize(Mem *p){ #endif /* -** The next global variable is incremented each type the OP_Found opcode +** The next global variable is incremented each time the OP_Found opcode ** is executed. This is used to test whether or not the foreign key ** operation implemented using OP_FkIsZero is working. This variable ** has no function other than to help verify the correct operation of the @@ -66157,6 +67115,34 @@ SQLITE_API int sqlite3_found_count = 0; # define UPDATE_MAX_BLOBSIZE(P) #endif +/* +** Invoke the VDBE coverage callback, if that callback is defined. This +** feature is used for test suite validation only and does not appear an +** production builds. +** +** M is an integer, 2 or 3, that indices how many different ways the +** branch can go. It is usually 2. "I" is the direction the branch +** goes. 0 means falls through. 1 means branch is taken. 2 means the +** second alternative branch is taken. +*/ +#if !defined(SQLITE_VDBE_COVERAGE) +# define VdbeBranchTaken(I,M) +#else +# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ + M = iSrcLine; + /* Assert the truth of VdbeCoverageAlwaysTaken() and + ** VdbeCoverageNeverTaken() */ + assert( (M & I)==I ); + }else{ + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, + iSrcLine,I,M); + } + } +#endif + /* ** Convert the given register into a string if it isn't one ** already. Return non-zero if a malloc() fails. @@ -66174,38 +67160,14 @@ SQLITE_API int sqlite3_found_count = 0; ** ** This routine converts an ephemeral string into a dynamically allocated ** string that the register itself controls. In other words, it -** converts an MEM_Ephem string into an MEM_Dyn string. +** converts an MEM_Ephem string into a string with P.z==P.zMalloc. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* Return true if the cursor was opened using the OP_OpenSorter opcode. */ -# define isSorter(x) ((x)->pSorter!=0) - -/* -** Argument pMem points at a register that will be passed to a -** user-defined function or returned to the user as the result of a query. -** This routine sets the pMem->type variable used by the sqlite3_value_*() -** routines. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){ - int flags = pMem->flags; - if( flags & MEM_Null ){ - pMem->type = SQLITE_NULL; - } - else if( flags & MEM_Int ){ - pMem->type = SQLITE_INTEGER; - } - else if( flags & MEM_Real ){ - pMem->type = SQLITE_FLOAT; - } - else if( flags & MEM_Str ){ - pMem->type = SQLITE_TEXT; - }else{ - pMem->type = SQLITE_BLOB; - } -} +#define isSorter(x) ((x)->pSorter!=0) /* ** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL @@ -66335,12 +67297,13 @@ static void applyAffinity( ** loss of information and return the revised type of the argument. */ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ - Mem *pMem = (Mem*)pVal; - if( pMem->type==SQLITE_TEXT ){ + int eType = sqlite3_value_type(pVal); + if( eType==SQLITE_TEXT ){ + Mem *pMem = (Mem*)pVal; applyNumericAffinity(pMem); - sqlite3VdbeMemStoreType(pMem); + eType = sqlite3_value_type(pVal); } - return pMem->type; + return eType; } /* @@ -66443,7 +67406,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ ** Print the value of a register for tracing purposes: */ static void memTracePrint(Mem *p){ - if( p->flags & MEM_Invalid ){ + if( p->flags & MEM_Undefined ){ printf(" undefined"); }else if( p->flags & MEM_Null ){ printf(" NULL"); @@ -66576,20 +67539,6 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } #endif -/* -** The CHECK_FOR_INTERRUPT macro defined here looks to see if the -** sqlite3_interrupt() routine has been called. If it has been, then -** processing of the VDBE program is interrupted. -** -** This macro added to every instruction that does a jump in order to -** implement a loop. This test used to be on every single instruction, -** but that meant we more testing than we needed. By only testing the -** flag on jump instructions, we get a (small) speed improvement. -*/ -#define CHECK_FOR_INTERRUPT \ - if( db->u1.isInterrupted ) goto abort_due_to_interrupt; - - #ifndef NDEBUG /* ** This function is only called from within an assert() expression. It @@ -66612,35 +67561,8 @@ static int checkSavepointCount(sqlite3 *db){ /* -** Execute as much of a VDBE program as we can then return. -** -** sqlite3VdbeMakeReady() must be called before this routine in order to -** close the program with a final OP_Halt and to set up the callbacks -** and the error message pointer. -** -** Whenever a row or result data is available, this routine will either -** invoke the result callback (if there is one) or return with -** SQLITE_ROW. -** -** If an attempt is made to open a locked database, then this routine -** will either invoke the busy callback (if there is one) or it will -** return SQLITE_BUSY. -** -** If an error occurs, an error message is written to memory obtained -** from sqlite3_malloc() and p->zErrMsg is made to point to that memory. -** The error code is stored in p->rc and this routine returns SQLITE_ERROR. -** -** If the callback ever returns non-zero, then the program exits -** immediately. There will be no error message but the p->rc field is -** set to SQLITE_ABORT and this routine will return SQLITE_ERROR. -** -** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this -** routine to return SQLITE_ERROR. -** -** Other fatal errors return SQLITE_ERROR. -** -** After this routine has finished, sqlite3VdbeFinalize() should be -** used to clean up the mess that was left behind. +** Execute as much of a VDBE program as we can. +** This is the core of sqlite3_step(). */ SQLITE_PRIVATE int sqlite3VdbeExec( Vdbe *p /* The VDBE */ @@ -66666,431 +67588,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec( i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ - int origPc; /* Program counter at start of opcode */ -#endif - /******************************************************************** - ** Automatically generated code - ** - ** The following union is automatically generated by the - ** vdbe-compress.tcl script. The purpose of this union is to - ** reduce the amount of stack space required by this function. - ** See comments in the vdbe-compress.tcl script for details. - */ - union vdbeExecUnion { - struct OP_Yield_stack_vars { - int pcDest; - } aa; - struct OP_Halt_stack_vars { - const char *zType; - const char *zLogFmt; - } ab; - struct OP_Null_stack_vars { - int cnt; - u16 nullFlag; - } ac; - struct OP_Variable_stack_vars { - Mem *pVar; /* Value being transferred */ - } ad; - struct OP_Move_stack_vars { - char *zMalloc; /* Holding variable for allocated memory */ - int n; /* Number of registers left to copy */ - int p1; /* Register to copy from */ - int p2; /* Register to copy to */ - } ae; - struct OP_Copy_stack_vars { - int n; - } af; - struct OP_ResultRow_stack_vars { - Mem *pMem; - int i; - } ag; - struct OP_Concat_stack_vars { - i64 nByte; - } ah; - struct OP_Remainder_stack_vars { - char bIntint; /* Started out as two integer operands */ - int flags; /* Combined MEM_* flags from both inputs */ - i64 iA; /* Integer value of left operand */ - i64 iB; /* Integer value of right operand */ - double rA; /* Real value of left operand */ - double rB; /* Real value of right operand */ - } ai; - struct OP_Function_stack_vars { - int i; - Mem *pArg; - sqlite3_context ctx; - sqlite3_value **apVal; - int n; - } aj; - struct OP_ShiftRight_stack_vars { - i64 iA; - u64 uA; - i64 iB; - u8 op; - } ak; - struct OP_Ge_stack_vars { - int res; /* Result of the comparison of pIn1 against pIn3 */ - char affinity; /* Affinity to use for comparison */ - u16 flags1; /* Copy of initial value of pIn1->flags */ - u16 flags3; /* Copy of initial value of pIn3->flags */ - } al; - struct OP_Compare_stack_vars { - int n; - int i; - int p1; - int p2; - const KeyInfo *pKeyInfo; - int idx; - CollSeq *pColl; /* Collating sequence to use on this term */ - int bRev; /* True for DESCENDING sort order */ - } am; - struct OP_Or_stack_vars { - int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - } an; - struct OP_IfNot_stack_vars { - int c; - } ao; - struct OP_Column_stack_vars { - i64 payloadSize64; /* Number of bytes in the record */ - int p2; /* column number to retrieve */ - VdbeCursor *pC; /* The VDBE cursor */ - BtCursor *pCrsr; /* The BTree cursor */ - u32 *aType; /* aType[i] holds the numeric type of the i-th column */ - u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ - int len; /* The length of the serialized data for the column */ - int i; /* Loop counter */ - Mem *pDest; /* Where to write the extracted value */ - Mem sMem; /* For storing the record being decoded */ - const u8 *zData; /* Part of the record being decoded */ - const u8 *zHdr; /* Next unparsed byte of the header */ - const u8 *zEndHdr; /* Pointer to first byte after the header */ - u32 offset; /* Offset into the data */ - u32 szField; /* Number of bytes in the content of a field */ - u32 avail; /* Number of bytes of available data */ - u32 t; /* A type code from the record header */ - Mem *pReg; /* PseudoTable input register */ - } ap; - struct OP_Affinity_stack_vars { - const char *zAffinity; /* The affinity to be applied */ - char cAff; /* A single character of affinity */ - } aq; - struct OP_MakeRecord_stack_vars { - u8 *zNewRecord; /* A buffer to hold the data for the new record */ - Mem *pRec; /* The new record */ - u64 nData; /* Number of bytes of data space */ - int nHdr; /* Number of bytes of header space */ - i64 nByte; /* Data space required for this record */ - int nZero; /* Number of zero bytes at the end of the record */ - int nVarint; /* Number of bytes in a varint */ - u32 serial_type; /* Type field */ - Mem *pData0; /* First field to be combined into the record */ - Mem *pLast; /* Last field of the record */ - int nField; /* Number of fields in the record */ - char *zAffinity; /* The affinity string for the record */ - int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ - int len; /* Length of a field */ - } ar; - struct OP_Count_stack_vars { - i64 nEntry; - BtCursor *pCrsr; - } as; - struct OP_Savepoint_stack_vars { - int p1; /* Value of P1 operand */ - char *zName; /* Name of savepoint */ - int nName; - Savepoint *pNew; - Savepoint *pSavepoint; - Savepoint *pTmp; - int iSavepoint; - int ii; - } at; - struct OP_AutoCommit_stack_vars { - int desiredAutoCommit; - int iRollback; - int turnOnAC; - } au; - struct OP_Transaction_stack_vars { - Btree *pBt; - } av; - struct OP_ReadCookie_stack_vars { - int iMeta; - int iDb; - int iCookie; - } aw; - struct OP_SetCookie_stack_vars { - Db *pDb; - } ax; - struct OP_VerifyCookie_stack_vars { - int iMeta; - int iGen; - Btree *pBt; - } ay; - struct OP_OpenWrite_stack_vars { - int nField; - KeyInfo *pKeyInfo; - int p2; - int iDb; - int wrFlag; - Btree *pX; - VdbeCursor *pCur; - Db *pDb; - } az; - struct OP_OpenEphemeral_stack_vars { - VdbeCursor *pCx; - KeyInfo *pKeyInfo; - } ba; - struct OP_SorterOpen_stack_vars { - VdbeCursor *pCx; - } bb; - struct OP_OpenPseudo_stack_vars { - VdbeCursor *pCx; - } bc; - struct OP_SeekGt_stack_vars { - int res; - int oc; - VdbeCursor *pC; - UnpackedRecord r; - int nField; - i64 iKey; /* The rowid we are to seek to */ - } bd; - struct OP_Seek_stack_vars { - VdbeCursor *pC; - } be; - struct OP_Found_stack_vars { - int alreadyExists; - int ii; - VdbeCursor *pC; - int res; - char *pFree; - UnpackedRecord *pIdxKey; - UnpackedRecord r; - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7]; - } bf; - struct OP_NotExists_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - u64 iKey; - } bg; - struct OP_NewRowid_stack_vars { - i64 v; /* The new rowid */ - VdbeCursor *pC; /* Cursor of table to get the new rowid */ - int res; /* Result of an sqlite3BtreeLast() */ - int cnt; /* Counter to limit the number of searches */ - Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ - VdbeFrame *pFrame; /* Root frame of VDBE */ - } bh; - struct OP_InsertInt_stack_vars { - Mem *pData; /* MEM cell holding data for the record to be inserted */ - Mem *pKey; /* MEM cell holding key for the record */ - i64 iKey; /* The integer ROWID or key for the record to be inserted */ - VdbeCursor *pC; /* Cursor to table into which insert is written */ - int nZero; /* Number of zero-bytes to append */ - int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ - const char *zDb; /* database name - used by the update hook */ - const char *zTbl; /* Table name - used by the opdate hook */ - int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ - } bi; - struct OP_Delete_stack_vars { - i64 iKey; - VdbeCursor *pC; - } bj; - struct OP_SorterCompare_stack_vars { - VdbeCursor *pC; - int res; - int nIgnore; - } bk; - struct OP_SorterData_stack_vars { - VdbeCursor *pC; - } bl; - struct OP_RowData_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - u32 n; - i64 n64; - } bm; - struct OP_Rowid_stack_vars { - VdbeCursor *pC; - i64 v; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - } bn; - struct OP_NullRow_stack_vars { - VdbeCursor *pC; - } bo; - struct OP_Last_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - } bp; - struct OP_Rewind_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - } bq; - struct OP_SorterNext_stack_vars { - VdbeCursor *pC; - int res; - } br; - struct OP_IdxInsert_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int nKey; - const char *zKey; - } bs; - struct OP_IdxDelete_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - UnpackedRecord r; - } bt; - struct OP_IdxRowid_stack_vars { - BtCursor *pCrsr; - VdbeCursor *pC; - i64 rowid; - } bu; - struct OP_IdxGE_stack_vars { - VdbeCursor *pC; - int res; - UnpackedRecord r; - } bv; - struct OP_Destroy_stack_vars { - int iMoved; - int iCnt; - Vdbe *pVdbe; - int iDb; - } bw; - struct OP_Clear_stack_vars { - int nChange; - } bx; - struct OP_CreateTable_stack_vars { - int pgno; - int flags; - Db *pDb; - } by; - struct OP_ParseSchema_stack_vars { - int iDb; - const char *zMaster; - char *zSql; - InitData initData; - } bz; - struct OP_IntegrityCk_stack_vars { - int nRoot; /* Number of tables to check. (Number of root pages.) */ - int *aRoot; /* Array of rootpage numbers for tables to be checked */ - int j; /* Loop counter */ - int nErr; /* Number of errors reported */ - char *z; /* Text of the error report */ - Mem *pnErr; /* Register keeping track of errors remaining */ - } ca; - struct OP_RowSetRead_stack_vars { - i64 val; - } cb; - struct OP_RowSetTest_stack_vars { - int iSet; - int exists; - } cc; - struct OP_Program_stack_vars { - int nMem; /* Number of memory registers for sub-program */ - int nByte; /* Bytes of runtime space required for sub-program */ - Mem *pRt; /* Register to allocate runtime space */ - Mem *pMem; /* Used to iterate through memory cells */ - Mem *pEnd; /* Last memory cell in new array */ - VdbeFrame *pFrame; /* New vdbe frame to execute in */ - SubProgram *pProgram; /* Sub-program to execute */ - void *t; /* Token identifying trigger */ - } cd; - struct OP_Param_stack_vars { - VdbeFrame *pFrame; - Mem *pIn; - } ce; - struct OP_MemMax_stack_vars { - Mem *pIn1; - VdbeFrame *pFrame; - } cf; - struct OP_AggStep_stack_vars { - int n; - int i; - Mem *pMem; - Mem *pRec; - sqlite3_context ctx; - sqlite3_value **apVal; - } cg; - struct OP_AggFinal_stack_vars { - Mem *pMem; - } ch; - struct OP_Checkpoint_stack_vars { - int i; /* Loop counter */ - int aRes[3]; /* Results */ - Mem *pMem; /* Write results here */ - } ci; - struct OP_JournalMode_stack_vars { - Btree *pBt; /* Btree to change journal mode of */ - Pager *pPager; /* Pager associated with pBt */ - int eNew; /* New journal mode */ - int eOld; /* The old journal mode */ -#ifndef SQLITE_OMIT_WAL - const char *zFilename; /* Name of database file for pPager */ #endif - } cj; - struct OP_IncrVacuum_stack_vars { - Btree *pBt; - } ck; - struct OP_VBegin_stack_vars { - VTable *pVTab; - } cl; - struct OP_VOpen_stack_vars { - VdbeCursor *pCur; - sqlite3_vtab_cursor *pVtabCursor; - sqlite3_vtab *pVtab; - sqlite3_module *pModule; - } cm; - struct OP_VFilter_stack_vars { - int nArg; - int iQuery; - const sqlite3_module *pModule; - Mem *pQuery; - Mem *pArgc; - sqlite3_vtab_cursor *pVtabCursor; - sqlite3_vtab *pVtab; - VdbeCursor *pCur; - int res; - int i; - Mem **apArg; - } cn; - struct OP_VColumn_stack_vars { - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - Mem *pDest; - sqlite3_context sContext; - } co; - struct OP_VNext_stack_vars { - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - int res; - VdbeCursor *pCur; - } cp; - struct OP_VRename_stack_vars { - sqlite3_vtab *pVtab; - Mem *pName; - } cq; - struct OP_VUpdate_stack_vars { - sqlite3_vtab *pVtab; - sqlite3_module *pModule; - int nArg; - int i; - sqlite_int64 rowid; - Mem **apArg; - Mem *pX; - } cr; - struct OP_Trace_stack_vars { - char *zTrace; - char *z; - } cs; - } u; - /* End automatically generated code - ********************************************************************/ + /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); @@ -67106,7 +67605,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; - CHECK_FOR_INTERRUPT; + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; sqlite3VdbeIOTraceSql(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( db->xProgress ){ @@ -67150,7 +67649,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( pc>=0 && pcnOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE - origPc = pc; start = sqlite3Hwtime(); #endif nVmStep++; @@ -67198,18 +67696,21 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); } if( (pOp->opflags & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p2]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p3]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); } if( (pOp->opflags & OPFLG_OUT2)!=0 ){ @@ -67267,6 +67768,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec( ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. +** +** The P1 parameter is not actually used by this opcode. However, it +** is sometimes set to 1 instead of 0 as a hint to the command-line shell +** that this Goto is the bottom of a loop and that the lines from P2 down +** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ pc = pOp->p2 - 1; @@ -67282,7 +67788,7 @@ case OP_Goto: { /* jump */ ** checks on every opcode. This helps sqlite3_step() to run about 1.5% ** faster according to "valgrind --tool=cachegrind" */ check_for_interrupt: - CHECK_FOR_INTERRUPT; + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Call the progress callback if it is configured and the required number ** of VDBE ops have been executed (either since this invocation of @@ -67311,7 +67817,7 @@ check_for_interrupt: case OP_Gosub: { /* jump */ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); + assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; pIn1->u.i = pc; @@ -67322,35 +67828,79 @@ case OP_Gosub: { /* jump */ /* Opcode: Return P1 * * * * ** -** Jump to the next instruction after the address in register P1. +** Jump to the next instruction after the address in register P1. After +** the jump, register P1 becomes undefined. */ case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags & MEM_Int ); + assert( pIn1->flags==MEM_Int ); pc = (int)pIn1->u.i; + pIn1->flags = MEM_Undefined; + break; +} + +/* Opcode: InitCoroutine P1 P2 P3 * * +** +** Set up register P1 so that it will OP_Yield to the co-routine +** located at address P3. +** +** If P2!=0 then the co-routine implementation immediately follows +** this opcode. So jump over the co-routine implementation to +** address P2. +*/ +case OP_InitCoroutine: { /* jump */ + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + assert( pOp->p2>=0 && pOp->p2nOp ); + assert( pOp->p3>=0 && pOp->p3nOp ); + pOut = &aMem[pOp->p1]; + assert( !VdbeMemDynamic(pOut) ); + pOut->u.i = pOp->p3 - 1; + pOut->flags = MEM_Int; + if( pOp->p2 ) pc = pOp->p2 - 1; + break; +} + +/* Opcode: EndCoroutine P1 * * * * +** +** The instruction at the address in register P1 is an OP_Yield. +** Jump to the P2 parameter of that OP_Yield. +** After the jump, register P1 becomes undefined. +*/ +case OP_EndCoroutine: { /* in1 */ + VdbeOp *pCaller; + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags==MEM_Int ); + assert( pIn1->u.i>=0 && pIn1->u.inOp ); + pCaller = &aOp[pIn1->u.i]; + assert( pCaller->opcode==OP_Yield ); + assert( pCaller->p2>=0 && pCaller->p2nOp ); + pc = pCaller->p2 - 1; + pIn1->flags = MEM_Undefined; break; } -/* Opcode: Yield P1 * * * * +/* Opcode: Yield P1 P2 * * * ** ** Swap the program counter with the value in register P1. +** +** If the co-routine ends with OP_Yield or OP_Return then continue +** to the next instruction. But if the co-routine ends with +** OP_EndCoroutine, jump immediately to P2. */ -case OP_Yield: { /* in1 */ -#if 0 /* local variables moved into u.aa */ +case OP_Yield: { /* in1, jump */ int pcDest; -#endif /* local variables moved into u.aa */ pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); + assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; - u.aa.pcDest = (int)pIn1->u.i; + pcDest = (int)pIn1->u.i; pIn1->u.i = pc; REGISTER_TRACE(pOp->p1, pIn1); - pc = u.aa.pcDest; + pc = pcDest; break; } /* Opcode: HaltIfNull P1 P2 P3 P4 P5 -** Synopsis: if r[P3] null then halt +** Synopsis: if r[P3]=null halt ** ** Check the value in register P3. If it is NULL then Halt using ** parameter P1, P2, and P4 as if this were a Halt instruction. If the @@ -67394,10 +67944,8 @@ case OP_HaltIfNull: { /* in3 */ ** is the same as executing Halt. */ case OP_Halt: { -#if 0 /* local variables moved into u.ab */ const char *zType; const char *zLogFmt; -#endif /* local variables moved into u.ab */ if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ @@ -67408,7 +67956,7 @@ case OP_Halt: { pc = sqlite3VdbeFrameRestore(pFrame); lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ - /* Instruction pc is the OP_Program that invoked the sub-program + /* Instruction pc is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified @@ -67431,21 +67979,21 @@ case OP_Halt: { testcase( pOp->p5==2 ); testcase( pOp->p5==3 ); testcase( pOp->p5==4 ); - u.ab.zType = azType[pOp->p5-1]; + zType = azType[pOp->p5-1]; }else{ - u.ab.zType = 0; + zType = 0; } - assert( u.ab.zType!=0 || pOp->p4.z!=0 ); - u.ab.zLogFmt = "abort at %d in [%s]: %s"; - if( u.ab.zType && pOp->p4.z ){ - sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s", - u.ab.zType, pOp->p4.z); + assert( zType!=0 || pOp->p4.z!=0 ); + zLogFmt = "abort at %d in [%s]: %s"; + if( zType && pOp->p4.z ){ + sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s", + zType, pOp->p4.z); }else if( pOp->p4.z ){ sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); }else{ - sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", u.ab.zType); + sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType); } - sqlite3_log(pOp->p1, u.ab.zLogFmt, pc, p->zSql, p->zErrMsg); + sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); @@ -67500,7 +68048,9 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ ** Synopsis: r[P2]='P4' ** ** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into an OP_String before it is executed for the first time. +** into an OP_String before it is executed for the first time. During +** this transformation, the length of string P4 is computed and stored +** as the P1 parameter. */ case OP_String8: { /* same as TK_STRING, out2-prerelease */ assert( pOp->p4.z!=0 ); @@ -67513,10 +68063,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ if( rc==SQLITE_TOOBIG ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->zMalloc==pOut->z ); - assert( pOut->flags & MEM_Dyn ); + assert( VdbeMemDynamic(pOut)==0 ); pOut->zMalloc = 0; pOut->flags |= MEM_Static; - pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ sqlite3DbFree(db, pOp->p4.z); } @@ -67559,25 +68108,37 @@ case OP_String: { /* out2-prerelease */ ** OP_Ne or OP_Eq. */ case OP_Null: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ac */ int cnt; u16 nullFlag; -#endif /* local variables moved into u.ac */ - u.ac.cnt = pOp->p3-pOp->p2; + cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem-p->nCursor) ); - pOut->flags = u.ac.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; - while( u.ac.cnt>0 ){ + pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; + while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); VdbeMemRelease(pOut); - pOut->flags = u.ac.nullFlag; - u.ac.cnt--; + pOut->flags = nullFlag; + cnt--; } break; } +/* Opcode: SoftNull P1 * * * * +** Synopsis: r[P1]=NULL +** +** Set register P1 to have the value NULL as seen by the OP_MakeRecord +** instruction, but do not free any string or blob memory associated with +** the register, so that if the value was a string or blob that was +** previously copied using OP_SCopy, the copies will continue to be valid. +*/ +case OP_SoftNull: { + assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + pOut = &aMem[pOp->p1]; + pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined; + break; +} -/* Opcode: Blob P1 P2 * P4 +/* Opcode: Blob P1 P2 * P4 * ** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this @@ -67596,21 +68157,19 @@ case OP_Blob: { /* out2-prerelease */ ** ** Transfer the values of bound parameter P1 into register P2 ** -** If the parameter is named, then its name appears in P4 and P3==1. +** If the parameter is named, then its name appears in P4. ** The P4 value is used by sqlite3_bind_parameter_name(). */ case OP_Variable: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ad */ Mem *pVar; /* Value being transferred */ -#endif /* local variables moved into u.ad */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] ); - u.ad.pVar = &p->aVar[pOp->p1 - 1]; - if( sqlite3VdbeMemTooBig(u.ad.pVar) ){ + pVar = &p->aVar[pOp->p1 - 1]; + if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } - sqlite3VdbeMemShallowCopy(pOut, u.ad.pVar, MEM_Static); + sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; } @@ -67624,44 +68183,44 @@ case OP_Variable: { /* out2-prerelease */ ** P1..P1+P3 and P2..P2+P3 to overlap. */ case OP_Move: { -#if 0 /* local variables moved into u.ae */ char *zMalloc; /* Holding variable for allocated memory */ int n; /* Number of registers left to copy */ int p1; /* Register to copy from */ int p2; /* Register to copy to */ -#endif /* local variables moved into u.ae */ - u.ae.n = pOp->p3; - u.ae.p1 = pOp->p1; - u.ae.p2 = pOp->p2; - assert( u.ae.n>=0 && u.ae.p1>0 && u.ae.p2>0 ); - assert( u.ae.p1+u.ae.n<=u.ae.p2 || u.ae.p2+u.ae.n<=u.ae.p1 ); + n = pOp->p3; + p1 = pOp->p1; + p2 = pOp->p2; + assert( n>=0 && p1>0 && p2>0 ); + assert( p1+n<=p2 || p2+n<=p1 ); - pIn1 = &aMem[u.ae.p1]; - pOut = &aMem[u.ae.p2]; + pIn1 = &aMem[p1]; + pOut = &aMem[p2]; do{ assert( pOut<=&aMem[(p->nMem-p->nCursor)] ); assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); - u.ae.zMalloc = pOut->zMalloc; - pOut->zMalloc = 0; - sqlite3VdbeMemMove(pOut, pIn1); + VdbeMemRelease(pOut); + zMalloc = pOut->zMalloc; + memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG - if( pOut->pScopyFrom>=&aMem[u.ae.p1] && pOut->pScopyFrom<&aMem[u.ae.p1+pOp->p3] ){ - pOut->pScopyFrom += u.ae.p1 - pOp->p2; + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ + pOut->pScopyFrom += p1 - pOp->p2; } #endif - pIn1->zMalloc = u.ae.zMalloc; - REGISTER_TRACE(u.ae.p2++, pOut); + pIn1->flags = MEM_Undefined; + pIn1->xDel = 0; + pIn1->zMalloc = zMalloc; + REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; - }while( u.ae.n-- ); + }while( n-- ); break; } /* Opcode: Copy P1 P2 P3 * * -** Synopsis: r[P2@P3]=r[P1@P3] +** Synopsis: r[P2@P3+1]=r[P1@P3+1] ** ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. ** @@ -67669,11 +68228,9 @@ case OP_Move: { ** is made of any string or blob constant. See also OP_SCopy. */ case OP_Copy: { -#if 0 /* local variables moved into u.af */ int n; -#endif /* local variables moved into u.af */ - u.af.n = pOp->p3; + n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); @@ -67683,8 +68240,8 @@ case OP_Copy: { #ifdef SQLITE_DEBUG pOut->pScopyFrom = 0; #endif - REGISTER_TRACE(pOp->p2+pOp->p3-u.af.n, pOut); - if( (u.af.n--)==0 ) break; + REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); + if( (n--)==0 ) break; pOut++; pIn1++; } @@ -67721,14 +68278,12 @@ case OP_SCopy: { /* out2 */ ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt -** structure to provide access to the top P1 values as the result -** row. +** structure to provide access to the r(P1)..r(P1+P2-1) values as +** the result row. */ case OP_ResultRow: { -#if 0 /* local variables moved into u.ag */ Mem *pMem; int i; -#endif /* local variables moved into u.ag */ assert( p->nResColumn==pOp->p2 ); assert( pOp->p1>0 ); assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 ); @@ -67754,8 +68309,8 @@ case OP_ResultRow: { break; } - /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then - ** DML statements invoke this opcode to return the number of rows + /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then + ** DML statements invoke this opcode to return the number of rows ** modified to the user. This is the only way that a VM that ** opens a statement transaction may invoke this opcode. ** @@ -67782,15 +68337,14 @@ case OP_ResultRow: { ** and have an assigned type. The results are de-ephemeralized as ** a side effect. */ - u.ag.pMem = p->pResultSet = &aMem[pOp->p1]; - for(u.ag.i=0; u.ag.ip2; u.ag.i++){ - assert( memIsValid(&u.ag.pMem[u.ag.i]) ); - Deephemeralize(&u.ag.pMem[u.ag.i]); - assert( (u.ag.pMem[u.ag.i].flags & MEM_Ephem)==0 - || (u.ag.pMem[u.ag.i].flags & (MEM_Str|MEM_Blob))==0 ); - sqlite3VdbeMemNulTerminate(&u.ag.pMem[u.ag.i]); - sqlite3VdbeMemStoreType(&u.ag.pMem[u.ag.i]); - REGISTER_TRACE(pOp->p1+u.ag.i, &u.ag.pMem[u.ag.i]); + pMem = p->pResultSet = &aMem[pOp->p1]; + for(i=0; ip2; i++){ + assert( memIsValid(&pMem[i]) ); + Deephemeralize(&pMem[i]); + assert( (pMem[i].flags & MEM_Ephem)==0 + || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 ); + sqlite3VdbeMemNulTerminate(&pMem[i]); + REGISTER_TRACE(pOp->p1+i, &pMem[i]); } if( db->mallocFailed ) goto no_mem; @@ -67815,9 +68369,7 @@ case OP_ResultRow: { ** to avoid a memcpy(). */ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ -#if 0 /* local variables moved into u.ah */ i64 nByte; -#endif /* local variables moved into u.ah */ pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; @@ -67830,22 +68382,22 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem; Stringify(pIn1, encoding); Stringify(pIn2, encoding); - u.ah.nByte = pIn1->n + pIn2->n; - if( u.ah.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + nByte = pIn1->n + pIn2->n; + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - MemSetTypeFlag(pOut, MEM_Str); - if( sqlite3VdbeMemGrow(pOut, (int)u.ah.nByte+2, pOut==pIn2) ){ + if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ goto no_mem; } + MemSetTypeFlag(pOut, MEM_Str); if( pOut!=pIn2 ){ memcpy(pOut->z, pIn2->z, pIn2->n); } memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); - pOut->z[u.ah.nByte]=0; - pOut->z[u.ah.nByte+1] = 0; + pOut->z[nByte]=0; + pOut->z[nByte+1] = 0; pOut->flags |= MEM_Term; - pOut->n = (int)u.ah.nByte; + pOut->n = (int)nByte; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; @@ -67894,79 +68446,77 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ -#if 0 /* local variables moved into u.ai */ char bIntint; /* Started out as two integer operands */ int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ -#endif /* local variables moved into u.ai */ pIn1 = &aMem[pOp->p1]; applyNumericAffinity(pIn1); pIn2 = &aMem[pOp->p2]; applyNumericAffinity(pIn2); pOut = &aMem[pOp->p3]; - u.ai.flags = pIn1->flags | pIn2->flags; - if( (u.ai.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; + flags = pIn1->flags | pIn2->flags; + if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ - u.ai.iA = pIn1->u.i; - u.ai.iB = pIn2->u.i; - u.ai.bIntint = 1; + iA = pIn1->u.i; + iB = pIn2->u.i; + bIntint = 1; switch( pOp->opcode ){ - case OP_Add: if( sqlite3AddInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break; - case OP_Subtract: if( sqlite3SubInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break; - case OP_Multiply: if( sqlite3MulInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break; + case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; + case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; + case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; case OP_Divide: { - if( u.ai.iA==0 ) goto arithmetic_result_is_null; - if( u.ai.iA==-1 && u.ai.iB==SMALLEST_INT64 ) goto fp_math; - u.ai.iB /= u.ai.iA; + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; + iB /= iA; break; } default: { - if( u.ai.iA==0 ) goto arithmetic_result_is_null; - if( u.ai.iA==-1 ) u.ai.iA = 1; - u.ai.iB %= u.ai.iA; + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 ) iA = 1; + iB %= iA; break; } } - pOut->u.i = u.ai.iB; + pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); }else{ - u.ai.bIntint = 0; + bIntint = 0; fp_math: - u.ai.rA = sqlite3VdbeRealValue(pIn1); - u.ai.rB = sqlite3VdbeRealValue(pIn2); + rA = sqlite3VdbeRealValue(pIn1); + rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ - case OP_Add: u.ai.rB += u.ai.rA; break; - case OP_Subtract: u.ai.rB -= u.ai.rA; break; - case OP_Multiply: u.ai.rB *= u.ai.rA; break; + case OP_Add: rB += rA; break; + case OP_Subtract: rB -= rA; break; + case OP_Multiply: rB *= rA; break; case OP_Divide: { /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - if( u.ai.rA==(double)0 ) goto arithmetic_result_is_null; - u.ai.rB /= u.ai.rA; + if( rA==(double)0 ) goto arithmetic_result_is_null; + rB /= rA; break; } default: { - u.ai.iA = (i64)u.ai.rA; - u.ai.iB = (i64)u.ai.rB; - if( u.ai.iA==0 ) goto arithmetic_result_is_null; - if( u.ai.iA==-1 ) u.ai.iA = 1; - u.ai.rB = (double)(u.ai.iB % u.ai.iA); + iA = (i64)rA; + iB = (i64)rB; + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 ) iA = 1; + rB = (double)(iB % iA); break; } } #ifdef SQLITE_OMIT_FLOATING_POINT - pOut->u.i = u.ai.rB; + pOut->u.i = rB; MemSetTypeFlag(pOut, MEM_Int); #else - if( sqlite3IsNaN(u.ai.rB) ){ + if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } - pOut->r = u.ai.rB; + pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); - if( (u.ai.flags & MEM_Real)==0 && !u.ai.bIntint ){ + if( (flags & MEM_Real)==0 && !bIntint ){ sqlite3VdbeIntegerAffinity(pOut); } #endif @@ -68019,56 +68569,53 @@ case OP_CollSeq: { ** See also: AggStep and AggFinal */ case OP_Function: { -#if 0 /* local variables moved into u.aj */ int i; Mem *pArg; sqlite3_context ctx; sqlite3_value **apVal; int n; -#endif /* local variables moved into u.aj */ - u.aj.n = pOp->p5; - u.aj.apVal = p->apArg; - assert( u.aj.apVal || u.aj.n==0 ); + n = pOp->p5; + apVal = p->apArg; + assert( apVal || n==0 ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); - assert( u.aj.n==0 || (pOp->p2>0 && pOp->p2+u.aj.n<=(p->nMem-p->nCursor)+1) ); - assert( pOp->p3p2 || pOp->p3>=pOp->p2+u.aj.n ); - u.aj.pArg = &aMem[pOp->p2]; - for(u.aj.i=0; u.aj.ip2+u.aj.i, u.aj.pArg); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); + pArg = &aMem[pOp->p2]; + for(i=0; ip2+i, pArg); } assert( pOp->p4type==P4_FUNCDEF ); - u.aj.ctx.pFunc = pOp->p4.pFunc; - u.aj.ctx.iOp = pc; - u.aj.ctx.pVdbe = p; + ctx.pFunc = pOp->p4.pFunc; + ctx.iOp = pc; + ctx.pVdbe = p; /* The output cell may already have a buffer allocated. Move - ** the pointer to u.aj.ctx.s so in case the user-function can use + ** the pointer to ctx.s so in case the user-function can use ** the already allocated buffer instead of allocating a new one. */ - memcpy(&u.aj.ctx.s, pOut, sizeof(Mem)); + memcpy(&ctx.s, pOut, sizeof(Mem)); pOut->flags = MEM_Null; pOut->xDel = 0; pOut->zMalloc = 0; - MemSetTypeFlag(&u.aj.ctx.s, MEM_Null); + MemSetTypeFlag(&ctx.s, MEM_Null); - u.aj.ctx.fErrorOrAux = 0; - if( u.aj.ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + ctx.fErrorOrAux = 0; + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); - u.aj.ctx.pColl = pOp[-1].p4.pColl; + ctx.pColl = pOp[-1].p4.pColl; } db->lastRowid = lastRowid; - (*u.aj.ctx.pFunc->xFunc)(&u.aj.ctx, u.aj.n, u.aj.apVal); /* IMP: R-24505-23230 */ + (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ lastRowid = db->lastRowid; if( db->mallocFailed ){ @@ -68077,23 +68624,23 @@ case OP_Function: { ** to return a value. The following call releases any resources ** associated with such a value. */ - sqlite3VdbeMemRelease(&u.aj.ctx.s); + sqlite3VdbeMemRelease(&ctx.s); goto no_mem; } /* If the function returned an error, throw an exception */ - if( u.aj.ctx.fErrorOrAux ){ - if( u.aj.ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.aj.ctx.s)); - rc = u.aj.ctx.isError; + if( ctx.fErrorOrAux ){ + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; } sqlite3VdbeDeleteAuxData(p, pc, pOp->p1); } /* Copy the result of the function into register P3 */ - sqlite3VdbeChangeEncoding(&u.aj.ctx.s, encoding); + sqlite3VdbeChangeEncoding(&ctx.s, encoding); assert( pOut->flags==MEM_Null ); - memcpy(pOut, &u.aj.ctx.s, sizeof(Mem)); + memcpy(pOut, &ctx.s, sizeof(Mem)); if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } @@ -68145,12 +68692,10 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ -#if 0 /* local variables moved into u.ak */ i64 iA; u64 uA; i64 iB; u8 op; -#endif /* local variables moved into u.ak */ pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; @@ -68159,38 +68704,38 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ sqlite3VdbeMemSetNull(pOut); break; } - u.ak.iA = sqlite3VdbeIntValue(pIn2); - u.ak.iB = sqlite3VdbeIntValue(pIn1); - u.ak.op = pOp->opcode; - if( u.ak.op==OP_BitAnd ){ - u.ak.iA &= u.ak.iB; - }else if( u.ak.op==OP_BitOr ){ - u.ak.iA |= u.ak.iB; - }else if( u.ak.iB!=0 ){ - assert( u.ak.op==OP_ShiftRight || u.ak.op==OP_ShiftLeft ); + iA = sqlite3VdbeIntValue(pIn2); + iB = sqlite3VdbeIntValue(pIn1); + op = pOp->opcode; + if( op==OP_BitAnd ){ + iA &= iB; + }else if( op==OP_BitOr ){ + iA |= iB; + }else if( iB!=0 ){ + assert( op==OP_ShiftRight || op==OP_ShiftLeft ); /* If shifting by a negative amount, shift in the other direction */ - if( u.ak.iB<0 ){ + if( iB<0 ){ assert( OP_ShiftRight==OP_ShiftLeft+1 ); - u.ak.op = 2*OP_ShiftLeft + 1 - u.ak.op; - u.ak.iB = u.ak.iB>(-64) ? -u.ak.iB : 64; + op = 2*OP_ShiftLeft + 1 - op; + iB = iB>(-64) ? -iB : 64; } - if( u.ak.iB>=64 ){ - u.ak.iA = (u.ak.iA>=0 || u.ak.op==OP_ShiftLeft) ? 0 : -1; + if( iB>=64 ){ + iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1; }else{ - memcpy(&u.ak.uA, &u.ak.iA, sizeof(u.ak.uA)); - if( u.ak.op==OP_ShiftLeft ){ - u.ak.uA <<= u.ak.iB; + memcpy(&uA, &iA, sizeof(uA)); + if( op==OP_ShiftLeft ){ + uA <<= iB; }else{ - u.ak.uA >>= u.ak.iB; + uA >>= iB; /* Sign-extend on a right shift of a negative number */ - if( u.ak.iA<0 ) u.ak.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ak.iB); + if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB); } - memcpy(&u.ak.iA, &u.ak.uA, sizeof(u.ak.iA)); + memcpy(&iA, &uA, sizeof(iA)); } } - pOut->u.i = u.ak.iA; + pOut->u.i = iA; MemSetTypeFlag(pOut, MEM_Int); break; } @@ -68222,6 +68767,7 @@ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); if( (pIn1->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; @@ -68260,7 +68806,7 @@ case OP_RealAffinity: { /* in1 */ ** ** Force the value in register P1 to be text. ** If the value is numeric, convert it to a string using the -** equivalent of printf(). Blob values are unchanged and +** equivalent of sprintf(). Blob values are unchanged and ** are afterwards simply interpreted as text. ** ** A NULL value is not changed by this routine. It remains NULL. @@ -68444,18 +68990,16 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */ case OP_Le: /* same as TK_LE, jump, in1, in3 */ case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ -#if 0 /* local variables moved into u.al */ int res; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */ -#endif /* local variables moved into u.al */ pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; - u.al.flags1 = pIn1->flags; - u.al.flags3 = pIn3->flags; - if( (u.al.flags1 | u.al.flags3)&MEM_Null ){ + flags1 = pIn1->flags; + flags3 = pIn3->flags; + if( (flags1 | flags3)&MEM_Null ){ /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ /* If SQLITE_NULLEQ is set (which will only happen if the operator is @@ -68463,65 +69007,71 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** or not both operands are null. */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); - assert( (u.al.flags1 & MEM_Cleared)==0 ); - if( (u.al.flags1&MEM_Null)!=0 - && (u.al.flags3&MEM_Null)!=0 - && (u.al.flags3&MEM_Cleared)==0 + assert( (flags1 & MEM_Cleared)==0 ); + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); + if( (flags1&MEM_Null)!=0 + && (flags3&MEM_Null)!=0 + && (flags3&MEM_Cleared)==0 ){ - u.al.res = 0; /* Results are equal */ + res = 0; /* Results are equal */ }else{ - u.al.res = 1; /* Results are not equal */ + res = 1; /* Results are not equal */ } }else{ /* SQLITE_NULLEQ is clear and at least one operand is NULL, ** then the result is always NULL. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. */ - if( pOp->p5 & SQLITE_JUMPIFNULL ){ - pc = pOp->p2-1; - }else if( pOp->p5 & SQLITE_STOREP2 ){ + if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); + }else{ + VdbeBranchTaken(2,3); + if( pOp->p5 & SQLITE_JUMPIFNULL ){ + pc = pOp->p2-1; + } } break; } }else{ /* Neither operand is NULL. Do a comparison. */ - u.al.affinity = pOp->p5 & SQLITE_AFF_MASK; - if( u.al.affinity ){ - applyAffinity(pIn1, u.al.affinity, encoding); - applyAffinity(pIn3, u.al.affinity, encoding); + affinity = pOp->p5 & SQLITE_AFF_MASK; + if( affinity ){ + applyAffinity(pIn1, affinity, encoding); + applyAffinity(pIn3, affinity, encoding); if( db->mallocFailed ) goto no_mem; } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); ExpandBlob(pIn1); ExpandBlob(pIn3); - u.al.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); + res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); } switch( pOp->opcode ){ - case OP_Eq: u.al.res = u.al.res==0; break; - case OP_Ne: u.al.res = u.al.res!=0; break; - case OP_Lt: u.al.res = u.al.res<0; break; - case OP_Le: u.al.res = u.al.res<=0; break; - case OP_Gt: u.al.res = u.al.res>0; break; - default: u.al.res = u.al.res>=0; break; + case OP_Eq: res = res==0; break; + case OP_Ne: res = res!=0; break; + case OP_Lt: res = res<0; break; + case OP_Le: res = res<=0; break; + case OP_Gt: res = res>0; break; + default: res = res>=0; break; } if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = u.al.res; + pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); - }else if( u.al.res ){ - pc = pOp->p2-1; + }else{ + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); + if( res ){ + pc = pOp->p2-1; + } } - /* Undo any changes made by applyAffinity() to the input registers. */ - pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.al.flags1&MEM_TypeMask); - pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.al.flags3&MEM_TypeMask); + pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); + pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); break; } @@ -68561,7 +69111,6 @@ case OP_Permutation: { ** and strings are less than blobs. */ case OP_Compare: { -#if 0 /* local variables moved into u.am */ int n; int i; int p1; @@ -68570,38 +69119,37 @@ case OP_Compare: { int idx; CollSeq *pColl; /* Collating sequence to use on this term */ int bRev; /* True for DESCENDING sort order */ -#endif /* local variables moved into u.am */ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; - u.am.n = pOp->p3; - u.am.pKeyInfo = pOp->p4.pKeyInfo; - assert( u.am.n>0 ); - assert( u.am.pKeyInfo!=0 ); - u.am.p1 = pOp->p1; - u.am.p2 = pOp->p2; + n = pOp->p3; + pKeyInfo = pOp->p4.pKeyInfo; + assert( n>0 ); + assert( pKeyInfo!=0 ); + p1 = pOp->p1; + p2 = pOp->p2; #if SQLITE_DEBUG if( aPermute ){ int k, mx = 0; - for(k=0; kmx ) mx = aPermute[k]; - assert( u.am.p1>0 && u.am.p1+mx<=(p->nMem-p->nCursor)+1 ); - assert( u.am.p2>0 && u.am.p2+mx<=(p->nMem-p->nCursor)+1 ); + for(k=0; kmx ) mx = aPermute[k]; + assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 ); + assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 ); }else{ - assert( u.am.p1>0 && u.am.p1+u.am.n<=(p->nMem-p->nCursor)+1 ); - assert( u.am.p2>0 && u.am.p2+u.am.n<=(p->nMem-p->nCursor)+1 ); + assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 ); + assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 ); } #endif /* SQLITE_DEBUG */ - for(u.am.i=0; u.am.inField ); - u.am.pColl = u.am.pKeyInfo->aColl[u.am.i]; - u.am.bRev = u.am.pKeyInfo->aSortOrder[u.am.i]; - iCompare = sqlite3MemCompare(&aMem[u.am.p1+u.am.idx], &aMem[u.am.p2+u.am.idx], u.am.pColl); + for(i=0; inField ); + pColl = pKeyInfo->aColl[i]; + bRev = pKeyInfo->aSortOrder[i]; + iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); if( iCompare ){ - if( u.am.bRev ) iCompare = -iCompare; + if( bRev ) iCompare = -iCompare; break; } } @@ -68617,11 +69165,11 @@ case OP_Compare: { */ case OP_Jump: { /* jump */ if( iCompare<0 ){ - pc = pOp->p1 - 1; + pc = pOp->p1 - 1; VdbeBranchTaken(0,3); }else if( iCompare==0 ){ - pc = pOp->p2 - 1; + pc = pOp->p2 - 1; VdbeBranchTaken(1,3); }else{ - pc = pOp->p3 - 1; + pc = pOp->p3 - 1; VdbeBranchTaken(2,3); } break; } @@ -68648,35 +69196,33 @@ case OP_Jump: { /* jump */ */ case OP_And: /* same as TK_AND, in1, in2, out3 */ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ -#if 0 /* local variables moved into u.an */ int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ -#endif /* local variables moved into u.an */ pIn1 = &aMem[pOp->p1]; if( pIn1->flags & MEM_Null ){ - u.an.v1 = 2; + v1 = 2; }else{ - u.an.v1 = sqlite3VdbeIntValue(pIn1)!=0; + v1 = sqlite3VdbeIntValue(pIn1)!=0; } pIn2 = &aMem[pOp->p2]; if( pIn2->flags & MEM_Null ){ - u.an.v2 = 2; + v2 = 2; }else{ - u.an.v2 = sqlite3VdbeIntValue(pIn2)!=0; + v2 = sqlite3VdbeIntValue(pIn2)!=0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; - u.an.v1 = and_logic[u.an.v1*3+u.an.v2]; + v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; - u.an.v1 = or_logic[u.an.v1*3+u.an.v2]; + v1 = or_logic[v1*3+v2]; } pOut = &aMem[pOp->p3]; - if( u.an.v1==2 ){ + if( v1==2 ){ MemSetTypeFlag(pOut, MEM_Null); }else{ - pOut->u.i = u.an.v1; + pOut->u.i = v1; MemSetTypeFlag(pOut, MEM_Int); } break; @@ -68721,10 +69267,13 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ /* Opcode: Once P1 P2 * * * ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, -** set the flag and fall through to the next instruction. +** set the flag and fall through to the next instruction. In other words, +** this opcode causes all following opcodes up through P2 (but not including +** P2) to run just once and to be skipped on subsequent times through the loop. */ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); + VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ pc = pOp->p2-1; }else{ @@ -68747,21 +69296,20 @@ case OP_Once: { /* jump */ */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ -#if 0 /* local variables moved into u.ao */ int c; -#endif /* local variables moved into u.ao */ pIn1 = &aMem[pOp->p1]; if( pIn1->flags & MEM_Null ){ - u.ao.c = pOp->p3; + c = pOp->p3; }else{ #ifdef SQLITE_OMIT_FLOATING_POINT - u.ao.c = sqlite3VdbeIntValue(pIn1)!=0; + c = sqlite3VdbeIntValue(pIn1)!=0; #else - u.ao.c = sqlite3VdbeRealValue(pIn1)!=0.0; + c = sqlite3VdbeRealValue(pIn1)!=0.0; #endif - if( pOp->opcode==OP_IfNot ) u.ao.c = !u.ao.c; + if( pOp->opcode==OP_IfNot ) c = !c; } - if( u.ao.c ){ + VdbeBranchTaken(c!=0, 2); + if( c ){ pc = pOp->p2-1; } break; @@ -68774,6 +69322,7 @@ case OP_IfNot: { /* jump, in1 */ */ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); if( (pIn1->flags & MEM_Null)!=0 ){ pc = pOp->p2 - 1; } @@ -68787,6 +69336,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ */ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ pc = pOp->p2 - 1; } @@ -68819,7 +69369,6 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ ** skipped for length() and all content loading can be skipped for typeof(). */ case OP_Column: { -#if 0 /* local variables moved into u.ap */ i64 payloadSize64; /* Number of bytes in the record */ int p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ @@ -68838,85 +69387,79 @@ case OP_Column: { u32 avail; /* Number of bytes of available data */ u32 t; /* A type code from the record header */ Mem *pReg; /* PseudoTable input register */ -#endif /* local variables moved into u.ap */ - u.ap.p2 = pOp->p2; + p2 = pOp->p2; assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - u.ap.pDest = &aMem[pOp->p3]; - memAboutToChange(p, u.ap.pDest); + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); assert( pOp->p1>=0 && pOp->p1nCursor ); - u.ap.pC = p->apCsr[pOp->p1]; - assert( u.ap.pC!=0 ); - assert( u.ap.p2nField ); - u.ap.aType = u.ap.pC->aType; - u.ap.aOffset = u.ap.aType + u.ap.pC->nField; + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( p2nField ); + aType = pC->aType; + aOffset = aType + pC->nField; #ifndef SQLITE_OMIT_VIRTUALTABLE - assert( u.ap.pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */ + assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */ #endif - u.ap.pCrsr = u.ap.pC->pCursor; - assert( u.ap.pCrsr!=0 || u.ap.pC->pseudoTableReg>0 ); /* u.ap.pCrsr NULL on PseudoTables */ - assert( u.ap.pCrsr!=0 || u.ap.pC->nullRow ); /* u.ap.pC->nullRow on PseudoTables */ + pCrsr = pC->pCursor; + assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */ + assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */ /* If the cursor cache is stale, bring it up-to-date */ - rc = sqlite3VdbeCursorMoveto(u.ap.pC); + rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; - if( u.ap.pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){ - if( u.ap.pC->nullRow ){ - if( u.ap.pCrsr==0 ){ - assert( u.ap.pC->pseudoTableReg>0 ); - u.ap.pReg = &aMem[u.ap.pC->pseudoTableReg]; - if( u.ap.pC->multiPseudo ){ - sqlite3VdbeMemShallowCopy(u.ap.pDest, u.ap.pReg+u.ap.p2, MEM_Ephem); - Deephemeralize(u.ap.pDest); - goto op_column_out; - } - assert( u.ap.pReg->flags & MEM_Blob ); - assert( memIsValid(u.ap.pReg) ); - u.ap.pC->payloadSize = u.ap.pC->szRow = u.ap.avail = u.ap.pReg->n; - u.ap.pC->aRow = (u8*)u.ap.pReg->z; + if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){ + if( pC->nullRow ){ + if( pCrsr==0 ){ + assert( pC->pseudoTableReg>0 ); + pReg = &aMem[pC->pseudoTableReg]; + assert( pReg->flags & MEM_Blob ); + assert( memIsValid(pReg) ); + pC->payloadSize = pC->szRow = avail = pReg->n; + pC->aRow = (u8*)pReg->z; }else{ - MemSetTypeFlag(u.ap.pDest, MEM_Null); + MemSetTypeFlag(pDest, MEM_Null); goto op_column_out; } }else{ - assert( u.ap.pCrsr ); - if( u.ap.pC->isTable==0 ){ - assert( sqlite3BtreeCursorIsValid(u.ap.pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ap.pCrsr, &u.ap.payloadSize64); + assert( pCrsr ); + if( pC->isTable==0 ){ + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the - ** payload size, so it is impossible for u.ap.payloadSize64 to be + ** payload size, so it is impossible for payloadSize64 to be ** larger than 32 bits. */ - assert( (u.ap.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ap.payloadSize64 ); - u.ap.pC->aRow = sqlite3BtreeKeyFetch(u.ap.pCrsr, &u.ap.avail); - u.ap.pC->payloadSize = (u32)u.ap.payloadSize64; + assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 ); + pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail); + pC->payloadSize = (u32)payloadSize64; }else{ - assert( sqlite3BtreeCursorIsValid(u.ap.pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ap.pCrsr, &u.ap.pC->payloadSize); + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize); assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - u.ap.pC->aRow = sqlite3BtreeDataFetch(u.ap.pCrsr, &u.ap.avail); + pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail); } - assert( u.ap.avail<=65536 ); /* Maximum page size is 64KiB */ - if( u.ap.pC->payloadSize <= (u32)u.ap.avail ){ - u.ap.pC->szRow = u.ap.pC->payloadSize; + assert( avail<=65536 ); /* Maximum page size is 64KiB */ + if( pC->payloadSize <= (u32)avail ){ + pC->szRow = pC->payloadSize; }else{ - u.ap.pC->szRow = u.ap.avail; + pC->szRow = avail; } - if( u.ap.pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } } - u.ap.pC->cacheStatus = p->cacheCtr; - u.ap.pC->iHdrOffset = getVarint32(u.ap.pC->aRow, u.ap.offset); - u.ap.pC->nHdrParsed = 0; - u.ap.aOffset[0] = u.ap.offset; - if( u.ap.availaRow does not have to hold the entire row, but it does at least - ** need to cover the header of the record. If u.ap.pC->aRow does not contain + pC->cacheStatus = p->cacheCtr; + pC->iHdrOffset = getVarint32(pC->aRow, offset); + pC->nHdrParsed = 0; + aOffset[0] = offset; + if( availaRow does not have to hold the entire row, but it does at least + ** need to cover the header of the record. If pC->aRow does not contain ** the complete header, then set it to zero, forcing the header to be ** dynamically allocated. */ - u.ap.pC->aRow = 0; - u.ap.pC->szRow = 0; + pC->aRow = 0; + pC->szRow = 0; } /* Make sure a corrupt database has not given us an oversize header. @@ -68928,72 +69471,72 @@ case OP_Column: { ** 3-byte type for each of the maximum of 32768 columns plus three ** extra bytes for the header length itself. 32768*3 + 3 = 98307. */ - if( u.ap.offset > 98307 || u.ap.offset > u.ap.pC->payloadSize ){ + if( offset > 98307 || offset > pC->payloadSize ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_error; } } - /* Make sure at least the first u.ap.p2+1 entries of the header have been - ** parsed and valid information is in u.ap.aOffset[] and u.ap.aType[]. + /* Make sure at least the first p2+1 entries of the header have been + ** parsed and valid information is in aOffset[] and aType[]. */ - if( u.ap.pC->nHdrParsed<=u.ap.p2 ){ + if( pC->nHdrParsed<=p2 ){ /* If there is more header available for parsing in the record, try - ** to extract additional fields up through the u.ap.p2+1-th field + ** to extract additional fields up through the p2+1-th field */ - if( u.ap.pC->iHdrOffsetaRow==0 ){ - memset(&u.ap.sMem, 0, sizeof(u.ap.sMem)); - rc = sqlite3VdbeMemFromBtree(u.ap.pCrsr, 0, u.ap.aOffset[0], - !u.ap.pC->isTable, &u.ap.sMem); + if( pC->iHdrOffsetaRow==0 ){ + memset(&sMem, 0, sizeof(sMem)); + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], + !pC->isTable, &sMem); if( rc!=SQLITE_OK ){ goto op_column_error; } - u.ap.zData = (u8*)u.ap.sMem.z; + zData = (u8*)sMem.z; }else{ - u.ap.zData = u.ap.pC->aRow; + zData = pC->aRow; } - - /* Fill in u.ap.aType[u.ap.i] and u.ap.aOffset[u.ap.i] values through the u.ap.p2-th field. */ - u.ap.i = u.ap.pC->nHdrParsed; - u.ap.offset = u.ap.aOffset[u.ap.i]; - u.ap.zHdr = u.ap.zData + u.ap.pC->iHdrOffset; - u.ap.zEndHdr = u.ap.zData + u.ap.aOffset[0]; - assert( u.ap.i<=u.ap.p2 && u.ap.zHdrnHdrParsed; + offset = aOffset[i]; + zHdr = zData + pC->iHdrOffset; + zEndHdr = zData + aOffset[0]; + assert( i<=p2 && zHdrnHdrParsed = u.ap.i; - u.ap.pC->iHdrOffset = (u32)(u.ap.zHdr - u.ap.zData); - if( u.ap.pC->aRow==0 ){ - sqlite3VdbeMemRelease(&u.ap.sMem); - u.ap.sMem.flags = MEM_Null; + i++; + aOffset[i] = offset; + }while( i<=p2 && zHdrnHdrParsed = i; + pC->iHdrOffset = (u32)(zHdr - zData); + if( pC->aRow==0 ){ + sqlite3VdbeMemRelease(&sMem); + sMem.flags = MEM_Null; } - + /* If we have read more header data than was contained in the header, ** or if the end of the last field appears to be past the end of the ** record, or if the end of the last field appears to be before the end - ** of the record (when all fields present), then we must be dealing + ** of the record (when all fields present), then we must be dealing ** with a corrupt database. */ - if( (u.ap.zHdr > u.ap.zEndHdr) - || (u.ap.offset > u.ap.pC->payloadSize) - || (u.ap.zHdr==u.ap.zEndHdr && u.ap.offset!=u.ap.pC->payloadSize) + if( (zHdr > zEndHdr) + || (offset > pC->payloadSize) + || (zHdr==zEndHdr && offset!=pC->payloadSize) ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_error; @@ -69001,77 +69544,78 @@ case OP_Column: { } /* If after trying to extra new entries from the header, nHdrParsed is - ** still not up to u.ap.p2, that means that the record has fewer than u.ap.p2 + ** still not up to p2, that means that the record has fewer than p2 ** columns. So the result will be either the default value or a NULL. */ - if( u.ap.pC->nHdrParsed<=u.ap.p2 ){ + if( pC->nHdrParsed<=p2 ){ if( pOp->p4type==P4_MEM ){ - sqlite3VdbeMemShallowCopy(u.ap.pDest, pOp->p4.pMem, MEM_Static); + sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); }else{ - MemSetTypeFlag(u.ap.pDest, MEM_Null); + MemSetTypeFlag(pDest, MEM_Null); } goto op_column_out; } } - /* Extract the content for the u.ap.p2+1-th column. Control can only - ** reach this point if u.ap.aOffset[u.ap.p2], u.ap.aOffset[u.ap.p2+1], and u.ap.aType[u.ap.p2] are + /* Extract the content for the p2+1-th column. Control can only + ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are ** all valid. */ - assert( u.ap.p2nHdrParsed ); + assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); - if( u.ap.pC->szRow>=u.ap.aOffset[u.ap.p2+1] ){ + assert( sqlite3VdbeCheckMemInvariants(pDest) ); + if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ - VdbeMemRelease(u.ap.pDest); - sqlite3VdbeSerialGet(u.ap.pC->aRow+u.ap.aOffset[u.ap.p2], u.ap.aType[u.ap.p2], u.ap.pDest); + VdbeMemRelease(pDest); + sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ - u.ap.t = u.ap.aType[u.ap.p2]; + t = aType[p2]; if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 - && ((u.ap.t>=12 && (u.ap.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) - || (u.ap.len = sqlite3VdbeSerialTypeLen(u.ap.t))==0 + && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) + || (len = sqlite3VdbeSerialTypeLen(t))==0 ){ /* Content is irrelevant for the typeof() function and for ** the length(X) function if X is a blob. So we might as well use ** bogus content rather than reading content from disk. NULL works - ** for text and blob and whatever is in the u.ap.payloadSize64 variable + ** for text and blob and whatever is in the payloadSize64 variable ** will work for everything else. Content is also irrelevant if ** the content length is 0. */ - u.ap.zData = u.ap.t<=13 ? (u8*)&u.ap.payloadSize64 : 0; - u.ap.sMem.zMalloc = 0; + zData = t<=13 ? (u8*)&payloadSize64 : 0; + sMem.zMalloc = 0; }else{ - memset(&u.ap.sMem, 0, sizeof(u.ap.sMem)); - sqlite3VdbeMemMove(&u.ap.sMem, u.ap.pDest); - rc = sqlite3VdbeMemFromBtree(u.ap.pCrsr, u.ap.aOffset[u.ap.p2], u.ap.len, !u.ap.pC->isTable, - &u.ap.sMem); + memset(&sMem, 0, sizeof(sMem)); + sqlite3VdbeMemMove(&sMem, pDest); + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, + &sMem); if( rc!=SQLITE_OK ){ goto op_column_error; } - u.ap.zData = (u8*)u.ap.sMem.z; + zData = (u8*)sMem.z; } - sqlite3VdbeSerialGet(u.ap.zData, u.ap.t, u.ap.pDest); + sqlite3VdbeSerialGet(zData, t, pDest); /* If we dynamically allocated space to hold the data (in the ** sqlite3VdbeMemFromBtree() call above) then transfer control of that - ** dynamically allocated space over to the u.ap.pDest structure. + ** dynamically allocated space over to the pDest structure. ** This prevents a memory copy. */ - if( u.ap.sMem.zMalloc ){ - assert( u.ap.sMem.z==u.ap.sMem.zMalloc ); - assert( !(u.ap.pDest->flags & MEM_Dyn) ); - assert( !(u.ap.pDest->flags & (MEM_Blob|MEM_Str)) || u.ap.pDest->z==u.ap.sMem.z ); - u.ap.pDest->flags &= ~(MEM_Ephem|MEM_Static); - u.ap.pDest->flags |= MEM_Term; - u.ap.pDest->z = u.ap.sMem.z; - u.ap.pDest->zMalloc = u.ap.sMem.zMalloc; + if( sMem.zMalloc ){ + assert( sMem.z==sMem.zMalloc ); + assert( VdbeMemDynamic(pDest)==0 ); + assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z ); + pDest->flags &= ~(MEM_Ephem|MEM_Static); + pDest->flags |= MEM_Term; + pDest->z = sMem.z; + pDest->zMalloc = sMem.zMalloc; } } - u.ap.pDest->enc = encoding; + pDest->enc = encoding; op_column_out: - rc = sqlite3VdbeMemMakeWriteable(u.ap.pDest); + Deephemeralize(pDest); op_column_error: - UPDATE_MAX_BLOBSIZE(u.ap.pDest); - REGISTER_TRACE(pOp->p3, u.ap.pDest); + UPDATE_MAX_BLOBSIZE(pDest); + REGISTER_TRACE(pOp->p3, pDest); break; } @@ -69085,20 +69629,17 @@ op_column_error: ** memory cell in the range. */ case OP_Affinity: { -#if 0 /* local variables moved into u.aq */ const char *zAffinity; /* The affinity to be applied */ char cAff; /* A single character of affinity */ -#endif /* local variables moved into u.aq */ - u.aq.zAffinity = pOp->p4.z; - assert( u.aq.zAffinity!=0 ); - assert( u.aq.zAffinity[pOp->p2]==0 ); + zAffinity = pOp->p4.z; + assert( zAffinity!=0 ); + assert( zAffinity[pOp->p2]==0 ); pIn1 = &aMem[pOp->p1]; - while( (u.aq.cAff = *(u.aq.zAffinity++))!=0 ){ + while( (cAff = *(zAffinity++))!=0 ){ assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); - ExpandBlob(pIn1); - applyAffinity(pIn1, u.aq.cAff, encoding); + applyAffinity(pIn1, cAff, encoding); pIn1++; } break; @@ -69121,7 +69662,6 @@ case OP_Affinity: { ** If P4 is NULL then all index fields have the affinity NONE. */ case OP_MakeRecord: { -#if 0 /* local variables moved into u.ar */ u8 *zNewRecord; /* A buffer to hold the data for the new record */ Mem *pRec; /* The new record */ u64 nData; /* Number of bytes of data space */ @@ -69135,102 +69675,120 @@ case OP_MakeRecord: { int nField; /* Number of fields in the record */ char *zAffinity; /* The affinity string for the record */ int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ + int i; /* Space used in zNewRecord[] header */ + int j; /* Space used in zNewRecord[] content */ int len; /* Length of a field */ -#endif /* local variables moved into u.ar */ /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------------ - ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | + ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | ** ------------------------------------------------------------------------ ** ** Data(0) is taken from register P1. Data(1) comes from register P1+1 ** and so froth. ** - ** Each type field is a varint representing the serial type of the + ** Each type field is a varint representing the serial type of the ** corresponding data element (see sqlite3VdbeSerialType()). The ** hdr-size field is also a varint which is the offset from the beginning ** of the record to data0. */ - u.ar.nData = 0; /* Number of bytes of data space */ - u.ar.nHdr = 0; /* Number of bytes of header space */ - u.ar.nZero = 0; /* Number of zero bytes at the end of the record */ - u.ar.nField = pOp->p1; - u.ar.zAffinity = pOp->p4.z; - assert( u.ar.nField>0 && pOp->p2>0 && pOp->p2+u.ar.nField<=(p->nMem-p->nCursor)+1 ); - u.ar.pData0 = &aMem[u.ar.nField]; - u.ar.nField = pOp->p2; - u.ar.pLast = &u.ar.pData0[u.ar.nField-1]; - u.ar.file_format = p->minWriteFileFormat; + nData = 0; /* Number of bytes of data space */ + nHdr = 0; /* Number of bytes of header space */ + nZero = 0; /* Number of zero bytes at the end of the record */ + nField = pOp->p1; + zAffinity = pOp->p4.z; + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 ); + pData0 = &aMem[nField]; + nField = pOp->p2; + pLast = &pData0[nField-1]; + file_format = p->minWriteFileFormat; /* Identify the output register */ assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); + /* Apply the requested affinity to all inputs + */ + assert( pData0<=pLast ); + if( zAffinity ){ + pRec = pData0; + do{ + applyAffinity(pRec++, *(zAffinity++), encoding); + assert( zAffinity[0]==0 || pRec<=pLast ); + }while( zAffinity[0] ); + } + /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ - for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){ - assert( memIsValid(u.ar.pRec) ); - if( u.ar.zAffinity ){ - applyAffinity(u.ar.pRec, u.ar.zAffinity[u.ar.pRec-u.ar.pData0], encoding); - } - if( u.ar.pRec->flags&MEM_Zero && u.ar.pRec->n>0 ){ - sqlite3VdbeMemExpandBlob(u.ar.pRec); - } - u.ar.serial_type = sqlite3VdbeSerialType(u.ar.pRec, u.ar.file_format); - u.ar.len = sqlite3VdbeSerialTypeLen(u.ar.serial_type); - u.ar.nData += u.ar.len; - u.ar.nHdr += sqlite3VarintLen(u.ar.serial_type); - if( u.ar.pRec->flags & MEM_Zero ){ - /* Only pure zero-filled BLOBs can be input to this Opcode. - ** We do not allow blobs with a prefix and a zero-filled tail. */ - u.ar.nZero += u.ar.pRec->u.nZero; - }else if( u.ar.len ){ - u.ar.nZero = 0; + pRec = pLast; + do{ + assert( memIsValid(pRec) ); + serial_type = sqlite3VdbeSerialType(pRec, file_format); + len = sqlite3VdbeSerialTypeLen(serial_type); + if( pRec->flags & MEM_Zero ){ + if( nData ){ + sqlite3VdbeMemExpandBlob(pRec); + }else{ + nZero += pRec->u.nZero; + len -= pRec->u.nZero; + } } - } + nData += len; + testcase( serial_type==127 ); + testcase( serial_type==128 ); + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); + }while( (--pRec)>=pData0 ); /* Add the initial header varint and total the size */ - u.ar.nHdr += u.ar.nVarint = sqlite3VarintLen(u.ar.nHdr); - if( u.ar.nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + testcase( nHdr==126 ); + testcase( nHdr==127 ); + if( nHdr<=126 ){ + /* The common case */ + nHdr += 1; + }else{ + /* Rare case of a really large header */ + nVarint = sqlite3VarintLen(nHdr); + nHdr += nVarint; + if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - /* Make sure the output register has a buffer large enough to store + /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to ** be one of the input registers (because the following call to ** sqlite3VdbeMemGrow() could clobber the value before it is used). */ - if( sqlite3VdbeMemGrow(pOut, (int)u.ar.nByte, 0) ){ + if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){ goto no_mem; } - u.ar.zNewRecord = (u8 *)pOut->z; + zNewRecord = (u8 *)pOut->z; /* Write the record */ - u.ar.i = putVarint32(u.ar.zNewRecord, u.ar.nHdr); - for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){ - u.ar.serial_type = sqlite3VdbeSerialType(u.ar.pRec, u.ar.file_format); - u.ar.i += putVarint32(&u.ar.zNewRecord[u.ar.i], u.ar.serial_type); /* serial type */ - } - for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){ /* serial data */ - u.ar.i += sqlite3VdbeSerialPut(&u.ar.zNewRecord[u.ar.i], (int)(u.ar.nByte-u.ar.i), u.ar.pRec,u.ar.file_format); - } - assert( u.ar.i==u.ar.nByte ); + i = putVarint32(zNewRecord, nHdr); + j = nHdr; + assert( pData0<=pLast ); + pRec = pData0; + do{ + serial_type = sqlite3VdbeSerialType(pRec, file_format); + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ + j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ + }while( (++pRec)<=pLast ); + assert( i==nHdr ); + assert( j==nByte ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - pOut->n = (int)u.ar.nByte; - pOut->flags = MEM_Blob | MEM_Dyn; + pOut->n = (int)nByte; + pOut->flags = MEM_Blob; pOut->xDel = 0; - if( u.ar.nZero ){ - pOut->u.nZero = u.ar.nZero; + if( nZero ){ + pOut->u.nZero = nZero; pOut->flags |= MEM_Zero; } pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ @@ -69247,15 +69805,14 @@ case OP_MakeRecord: { */ #ifndef SQLITE_OMIT_BTREECOUNT case OP_Count: { /* out2-prerelease */ -#if 0 /* local variables moved into u.as */ i64 nEntry; BtCursor *pCrsr; -#endif /* local variables moved into u.as */ - u.as.pCrsr = p->apCsr[pOp->p1]->pCursor; - assert( u.as.pCrsr ); - rc = sqlite3BtreeCount(u.as.pCrsr, &u.as.nEntry); - pOut->u.i = u.as.nEntry; + pCrsr = p->apCsr[pOp->p1]->pCursor; + assert( pCrsr ); + nEntry = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3BtreeCount(pCrsr, &nEntry); + pOut->u.i = nEntry; break; } #endif @@ -69267,7 +69824,6 @@ case OP_Count: { /* out2-prerelease */ ** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. */ case OP_Savepoint: { -#if 0 /* local variables moved into u.at */ int p1; /* Value of P1 operand */ char *zName; /* Name of savepoint */ int nName; @@ -69276,30 +69832,29 @@ case OP_Savepoint: { Savepoint *pTmp; int iSavepoint; int ii; -#endif /* local variables moved into u.at */ - u.at.p1 = pOp->p1; - u.at.zName = pOp->p4.z; + p1 = pOp->p1; + zName = pOp->p4.z; - /* Assert that the u.at.p1 parameter is valid. Also that if there is no open - ** transaction, then there cannot be any savepoints. + /* Assert that the p1 parameter is valid. Also that if there is no open + ** transaction, then there cannot be any savepoints. */ assert( db->pSavepoint==0 || db->autoCommit==0 ); - assert( u.at.p1==SAVEPOINT_BEGIN||u.at.p1==SAVEPOINT_RELEASE||u.at.p1==SAVEPOINT_ROLLBACK ); + assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); assert( db->pSavepoint || db->isTransactionSavepoint==0 ); assert( checkSavepointCount(db) ); assert( p->bIsReader ); - if( u.at.p1==SAVEPOINT_BEGIN ){ + if( p1==SAVEPOINT_BEGIN ){ if( db->nVdbeWrite>0 ){ - /* A new savepoint cannot be created if there are active write + /* A new savepoint cannot be created if there are active write ** statements (i.e. open read/write incremental blob handles). */ sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - " "SQL statements in progress"); rc = SQLITE_BUSY; }else{ - u.at.nName = sqlite3Strlen30(u.at.zName); + nName = sqlite3Strlen30(zName); #ifndef SQLITE_OMIT_VIRTUALTABLE /* This call is Ok even if this savepoint is actually a transaction @@ -69313,11 +69868,11 @@ case OP_Savepoint: { #endif /* Create a new savepoint structure. */ - u.at.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.at.nName+1); - if( u.at.pNew ){ - u.at.pNew->zName = (char *)&u.at.pNew[1]; - memcpy(u.at.pNew->zName, u.at.zName, u.at.nName+1); - + pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); + if( pNew ){ + pNew->zName = (char *)&pNew[1]; + memcpy(pNew->zName, zName, nName+1); + /* If there is no open transaction, then mark this as a special ** "transaction savepoint". */ if( db->autoCommit ){ @@ -69326,45 +69881,45 @@ case OP_Savepoint: { }else{ db->nSavepoint++; } - + /* Link the new savepoint into the database handle's list. */ - u.at.pNew->pNext = db->pSavepoint; - db->pSavepoint = u.at.pNew; - u.at.pNew->nDeferredCons = db->nDeferredCons; - u.at.pNew->nDeferredImmCons = db->nDeferredImmCons; + pNew->pNext = db->pSavepoint; + db->pSavepoint = pNew; + pNew->nDeferredCons = db->nDeferredCons; + pNew->nDeferredImmCons = db->nDeferredImmCons; } } }else{ - u.at.iSavepoint = 0; + iSavepoint = 0; /* Find the named savepoint. If there is no such savepoint, then an ** an error is returned to the user. */ for( - u.at.pSavepoint = db->pSavepoint; - u.at.pSavepoint && sqlite3StrICmp(u.at.pSavepoint->zName, u.at.zName); - u.at.pSavepoint = u.at.pSavepoint->pNext + pSavepoint = db->pSavepoint; + pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); + pSavepoint = pSavepoint->pNext ){ - u.at.iSavepoint++; + iSavepoint++; } - if( !u.at.pSavepoint ){ - sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.at.zName); + if( !pSavepoint ){ + sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName); rc = SQLITE_ERROR; - }else if( db->nVdbeWrite>0 && u.at.p1==SAVEPOINT_RELEASE ){ - /* It is not possible to release (commit) a savepoint if there are + }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ + /* It is not possible to release (commit) a savepoint if there are ** active write statements. */ - sqlite3SetString(&p->zErrMsg, db, + sqlite3SetString(&p->zErrMsg, db, "cannot release savepoint - SQL statements in progress" ); rc = SQLITE_BUSY; }else{ /* Determine whether or not this is a transaction savepoint. If so, - ** and this is a RELEASE command, then the current transaction - ** is committed. + ** and this is a RELEASE command, then the current transaction + ** is committed. */ - int isTransaction = u.at.pSavepoint->pNext==0 && db->isTransactionSavepoint; - if( isTransaction && u.at.p1==SAVEPOINT_RELEASE ){ + int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; + if( isTransaction && p1==SAVEPOINT_RELEASE ){ if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; } @@ -69378,52 +69933,52 @@ case OP_Savepoint: { db->isTransactionSavepoint = 0; rc = p->rc; }else{ - u.at.iSavepoint = db->nSavepoint - u.at.iSavepoint - 1; - if( u.at.p1==SAVEPOINT_ROLLBACK ){ - for(u.at.ii=0; u.at.iinDb; u.at.ii++){ - sqlite3BtreeTripAllCursors(db->aDb[u.at.ii].pBt, SQLITE_ABORT); + iSavepoint = db->nSavepoint - iSavepoint - 1; + if( p1==SAVEPOINT_ROLLBACK ){ + for(ii=0; iinDb; ii++){ + sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT); } } - for(u.at.ii=0; u.at.iinDb; u.at.ii++){ - rc = sqlite3BtreeSavepoint(db->aDb[u.at.ii].pBt, u.at.p1, u.at.iSavepoint); + for(ii=0; iinDb; ii++){ + rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } - if( u.at.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ + if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); db->flags = (db->flags | SQLITE_InternChanges); } } - - /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all + + /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all ** savepoints nested inside of the savepoint being operated on. */ - while( db->pSavepoint!=u.at.pSavepoint ){ - u.at.pTmp = db->pSavepoint; - db->pSavepoint = u.at.pTmp->pNext; - sqlite3DbFree(db, u.at.pTmp); + while( db->pSavepoint!=pSavepoint ){ + pTmp = db->pSavepoint; + db->pSavepoint = pTmp->pNext; + sqlite3DbFree(db, pTmp); db->nSavepoint--; } - /* If it is a RELEASE, then destroy the savepoint being operated on - ** too. If it is a ROLLBACK TO, then set the number of deferred + /* If it is a RELEASE, then destroy the savepoint being operated on + ** too. If it is a ROLLBACK TO, then set the number of deferred ** constraint violations present in the database to the value stored ** when the savepoint was created. */ - if( u.at.p1==SAVEPOINT_RELEASE ){ - assert( u.at.pSavepoint==db->pSavepoint ); - db->pSavepoint = u.at.pSavepoint->pNext; - sqlite3DbFree(db, u.at.pSavepoint); + if( p1==SAVEPOINT_RELEASE ){ + assert( pSavepoint==db->pSavepoint ); + db->pSavepoint = pSavepoint->pNext; + sqlite3DbFree(db, pSavepoint); if( !isTransaction ){ db->nSavepoint--; } }else{ - db->nDeferredCons = u.at.pSavepoint->nDeferredCons; - db->nDeferredImmCons = u.at.pSavepoint->nDeferredImmCons; + db->nDeferredCons = pSavepoint->nDeferredCons; + db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } if( !isTransaction ){ - rc = sqlite3VtabSavepoint(db, u.at.p1, u.at.iSavepoint); + rc = sqlite3VtabSavepoint(db, p1, iSavepoint); if( rc!=SQLITE_OK ) goto abort_due_to_error; } } @@ -69442,50 +69997,48 @@ case OP_Savepoint: { ** This instruction causes the VM to halt. */ case OP_AutoCommit: { -#if 0 /* local variables moved into u.au */ int desiredAutoCommit; int iRollback; int turnOnAC; -#endif /* local variables moved into u.au */ - u.au.desiredAutoCommit = pOp->p1; - u.au.iRollback = pOp->p2; - u.au.turnOnAC = u.au.desiredAutoCommit && !db->autoCommit; - assert( u.au.desiredAutoCommit==1 || u.au.desiredAutoCommit==0 ); - assert( u.au.desiredAutoCommit==1 || u.au.iRollback==0 ); + desiredAutoCommit = pOp->p1; + iRollback = pOp->p2; + turnOnAC = desiredAutoCommit && !db->autoCommit; + assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); + assert( desiredAutoCommit==1 || iRollback==0 ); assert( db->nVdbeActive>0 ); /* At least this one VM is active */ assert( p->bIsReader ); #if 0 - if( u.au.turnOnAC && u.au.iRollback && db->nVdbeActive>1 ){ + if( turnOnAC && iRollback && db->nVdbeActive>1 ){ /* If this instruction implements a ROLLBACK and other VMs are ** still running, and a transaction is active, return an error indicating - ** that the other VMs must complete first. + ** that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; }else #endif - if( u.au.turnOnAC && !u.au.iRollback && db->nVdbeWrite>0 ){ + if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ /* If this instruction implements a COMMIT and other VMs are writing - ** return an error indicating that the other VMs must complete first. + ** return an error indicating that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; - }else if( u.au.desiredAutoCommit!=db->autoCommit ){ - if( u.au.iRollback ){ - assert( u.au.desiredAutoCommit==1 ); + }else if( desiredAutoCommit!=db->autoCommit ){ + if( iRollback ){ + assert( desiredAutoCommit==1 ); sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); db->autoCommit = 1; }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ - db->autoCommit = (u8)u.au.desiredAutoCommit; + db->autoCommit = (u8)desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = pc; - db->autoCommit = (u8)(1-u.au.desiredAutoCommit); + db->autoCommit = (u8)(1-desiredAutoCommit); p->rc = rc = SQLITE_BUSY; goto vdbe_return; } @@ -69500,34 +70053,28 @@ case OP_AutoCommit: { goto vdbe_return; }else{ sqlite3SetString(&p->zErrMsg, db, - (!u.au.desiredAutoCommit)?"cannot start a transaction within a transaction":( - (u.au.iRollback)?"cannot rollback - no transaction is active": + (!desiredAutoCommit)?"cannot start a transaction within a transaction":( + (iRollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active")); - + rc = SQLITE_ERROR; } break; } -/* Opcode: Transaction P1 P2 * * * +/* Opcode: Transaction P1 P2 P3 P4 P5 ** -** Begin a transaction. The transaction ends when a Commit or Rollback -** opcode is encountered. Depending on the ON CONFLICT setting, the -** transaction might also be rolled back if an error is encountered. +** Begin a transaction on database P1 if a transaction is not already +** active. +** If P2 is non-zero, then a write-transaction is started, or if a +** read-transaction is already active, it is upgraded to a write-transaction. +** If P2 is zero, then a read-transaction is started. ** ** P1 is the index of the database file on which the transaction is ** started. Index 0 is the main database file and index 1 is the ** file used for temporary tables. Indices of 2 or more are used for ** attached databases. ** -** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is -** obtained on the database file when a write-transaction is started. No -** other process can start another write transaction while this transaction is -** underway. Starting a write transaction also creates a rollback journal. A -** write transaction must be started before any changes can be made to the -** database. If P2 is greater than or equal to 2 then an EXCLUSIVE lock is -** also obtained on the file. -** ** If a write-transaction is started and the Vdbe.usesStmtJournal flag is ** true (this flag is set if the Vdbe may modify more than one row and may ** throw an ABORT exception), a statement transaction may also be opened. @@ -69538,12 +70085,21 @@ case OP_AutoCommit: { ** entire transaction. If no error is encountered, the statement transaction ** will automatically commit when the VDBE halts. ** -** If P2 is zero, then a read-lock is obtained on the database file. +** If P5!=0 then this opcode also checks the schema cookie against P3 +** and the schema generation counter against P4. +** The cookie changes its value whenever the database schema changes. +** This operation is used to detect when that the cookie has changed +** and that the current process needs to reread the schema. If the schema +** cookie in P3 differs from the schema cookie in the database header or +** if the schema generation counter in P4 differs from the current +** generation counter, then an SQLITE_SCHEMA error is raised and execution +** halts. The sqlite3_step() wrapper function might then reprepare the +** statement and rerun it from the beginning. */ case OP_Transaction: { -#if 0 /* local variables moved into u.av */ Btree *pBt; -#endif /* local variables moved into u.av */ + int iMeta; + int iGen; assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); @@ -69553,10 +70109,10 @@ case OP_Transaction: { rc = SQLITE_READONLY; goto abort_due_to_error; } - u.av.pBt = db->aDb[pOp->p1].pBt; + pBt = db->aDb[pOp->p1].pBt; - if( u.av.pBt ){ - rc = sqlite3BtreeBeginTrans(u.av.pBt, pOp->p2); + if( pBt ){ + rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; @@ -69566,19 +70122,19 @@ case OP_Transaction: { goto abort_due_to_error; } - if( pOp->p2 && p->usesStmtJournal - && (db->autoCommit==0 || db->nVdbeRead>1) + if( pOp->p2 && p->usesStmtJournal + && (db->autoCommit==0 || db->nVdbeRead>1) ){ - assert( sqlite3BtreeIsInTrans(u.av.pBt) ); + assert( sqlite3BtreeIsInTrans(pBt) ); if( p->iStatement==0 ){ assert( db->nStatement>=0 && db->nSavepoint>=0 ); - db->nStatement++; + db->nStatement++; p->iStatement = db->nSavepoint + db->nStatement; } rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginStmt(u.av.pBt, p->iStatement); + rc = sqlite3BtreeBeginStmt(pBt, p->iStatement); } /* Store the current value of the database handles deferred constraint @@ -69587,6 +70143,35 @@ case OP_Transaction: { p->nStmtDefCons = db->nDeferredCons; p->nStmtDefImmCons = db->nDeferredImmCons; } + + /* Gather the schema version number for checking */ + sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); + iGen = db->aDb[pOp->p1].pSchema->iGeneration; + }else{ + iGen = iMeta = 0; + } + assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); + if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); + /* If the schema-cookie from the database file matches the cookie + ** stored with the in-memory representation of the schema, do + ** not reload the schema from the database file. + ** + ** If virtual-tables are in use, this is not just an optimization. + ** Often, v-tables store their data in other SQLite tables, which + ** are queried from within xNext() and other v-table methods using + ** prepared queries. If such a query is out-of-date, we do not want to + ** discard the database schema, as the user code implementing the + ** v-table would have to be ready for the sqlite3_vtab structure itself + ** to be invalidated whenever sqlite3_step() is called from within + ** a v-table method. + */ + if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ + sqlite3ResetOneSchema(db, pOp->p1); + } + p->expired = 1; + rc = SQLITE_SCHEMA; } break; } @@ -69604,22 +70189,20 @@ case OP_Transaction: { ** executing this instruction. */ case OP_ReadCookie: { /* out2-prerelease */ -#if 0 /* local variables moved into u.aw */ int iMeta; int iDb; int iCookie; -#endif /* local variables moved into u.aw */ assert( p->bIsReader ); - u.aw.iDb = pOp->p1; - u.aw.iCookie = pOp->p3; + iDb = pOp->p1; + iCookie = pOp->p3; assert( pOp->p3=0 && u.aw.iDbnDb ); - assert( db->aDb[u.aw.iDb].pBt!=0 ); - assert( (p->btreeMask & (((yDbMask)1)<=0 && iDbnDb ); + assert( db->aDb[iDb].pBt!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[u.aw.iDb].pBt, u.aw.iCookie, (u32 *)&u.aw.iMeta); - pOut->u.i = u.aw.iMeta; + sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta); + pOut->u.i = iMeta; break; } @@ -69634,27 +70217,25 @@ case OP_ReadCookie: { /* out2-prerelease */ ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { /* in3 */ -#if 0 /* local variables moved into u.ax */ Db *pDb; -#endif /* local variables moved into u.ax */ assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); assert( p->readOnly==0 ); - u.ax.pDb = &db->aDb[pOp->p1]; - assert( u.ax.pDb->pBt!=0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); pIn3 = &aMem[pOp->p3]; sqlite3VdbeMemIntegerify(pIn3); /* See note about index shifting on OP_ReadCookie */ - rc = sqlite3BtreeUpdateMeta(u.ax.pDb->pBt, pOp->p2, (int)pIn3->u.i); + rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); if( pOp->p2==BTREE_SCHEMA_VERSION ){ /* When the schema cookie changes, record the new cookie internally */ - u.ax.pDb->pSchema->schema_cookie = (int)pIn3->u.i; + pDb->pSchema->schema_cookie = (int)pIn3->u.i; db->flags |= SQLITE_InternChanges; }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ - u.ax.pDb->pSchema->file_format = (u8)pIn3->u.i; + pDb->pSchema->file_format = (u8)pIn3->u.i; } if( pOp->p1==1 ){ /* Invalidate all prepared statements whenever the TEMP database @@ -69665,68 +70246,6 @@ case OP_SetCookie: { /* in3 */ break; } -/* Opcode: VerifyCookie P1 P2 P3 * * -** -** Check the value of global database parameter number 0 (the -** schema version) and make sure it is equal to P2 and that the -** generation counter on the local schema parse equals P3. -** -** P1 is the database number which is 0 for the main database file -** and 1 for the file holding temporary tables and some higher number -** for auxiliary databases. -** -** The cookie changes its value whenever the database schema changes. -** This operation is used to detect when that the cookie has changed -** and that the current process needs to reread the schema. -** -** Either a transaction needs to have been started or an OP_Open needs -** to be executed (to establish a read lock) before this opcode is -** invoked. -*/ -case OP_VerifyCookie: { -#if 0 /* local variables moved into u.ay */ - int iMeta; - int iGen; - Btree *pBt; -#endif /* local variables moved into u.ay */ - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); - assert( p->bIsReader ); - u.ay.pBt = db->aDb[pOp->p1].pBt; - if( u.ay.pBt ){ - sqlite3BtreeGetMeta(u.ay.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ay.iMeta); - u.ay.iGen = db->aDb[pOp->p1].pSchema->iGeneration; - }else{ - u.ay.iGen = u.ay.iMeta = 0; - } - if( u.ay.iMeta!=pOp->p2 || u.ay.iGen!=pOp->p3 ){ - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); - /* If the schema-cookie from the database file matches the cookie - ** stored with the in-memory representation of the schema, do - ** not reload the schema from the database file. - ** - ** If virtual-tables are in use, this is not just an optimization. - ** Often, v-tables store their data in other SQLite tables, which - ** are queried from within xNext() and other v-table methods using - ** prepared queries. If such a query is out-of-date, we do not want to - ** discard the database schema, as the user code implementing the - ** v-table would have to be ready for the sqlite3_vtab structure itself - ** to be invalidated whenever sqlite3_step() is called from within - ** a v-table method. - */ - if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ay.iMeta ){ - sqlite3ResetOneSchema(db, pOp->p1); - } - - p->expired = 1; - rc = SQLITE_SCHEMA; - } - break; -} - /* Opcode: OpenRead P1 P2 P3 P4 P5 ** Synopsis: root=P2 iDb=P3 ** @@ -69780,7 +70299,6 @@ case OP_VerifyCookie: { */ case OP_OpenRead: case OP_OpenWrite: { -#if 0 /* local variables moved into u.az */ int nField; KeyInfo *pKeyInfo; int p2; @@ -69789,7 +70307,6 @@ case OP_OpenWrite: { Btree *pX; VdbeCursor *pCur; Db *pDb; -#endif /* local variables moved into u.az */ assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); @@ -69801,60 +70318,60 @@ case OP_OpenWrite: { break; } - u.az.nField = 0; - u.az.pKeyInfo = 0; - u.az.p2 = pOp->p2; - u.az.iDb = pOp->p3; - assert( u.az.iDb>=0 && u.az.iDbnDb ); - assert( (p->btreeMask & (((yDbMask)1)<aDb[u.az.iDb]; - u.az.pX = u.az.pDb->pBt; - assert( u.az.pX!=0 ); + nField = 0; + pKeyInfo = 0; + p2 = pOp->p2; + iDb = pOp->p3; + assert( iDb>=0 && iDbnDb ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[iDb]; + pX = pDb->pBt; + assert( pX!=0 ); if( pOp->opcode==OP_OpenWrite ){ - u.az.wrFlag = 1; - assert( sqlite3SchemaMutexHeld(db, u.az.iDb, 0) ); - if( u.az.pDb->pSchema->file_format < p->minWriteFileFormat ){ - p->minWriteFileFormat = u.az.pDb->pSchema->file_format; + wrFlag = 1; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + if( pDb->pSchema->file_format < p->minWriteFileFormat ){ + p->minWriteFileFormat = pDb->pSchema->file_format; } }else{ - u.az.wrFlag = 0; + wrFlag = 0; } if( pOp->p5 & OPFLAG_P2ISREG ){ - assert( u.az.p2>0 ); - assert( u.az.p2<=(p->nMem-p->nCursor) ); - pIn2 = &aMem[u.az.p2]; + assert( p2>0 ); + assert( p2<=(p->nMem-p->nCursor) ); + pIn2 = &aMem[p2]; assert( memIsValid(pIn2) ); assert( (pIn2->flags & MEM_Int)!=0 ); sqlite3VdbeMemIntegerify(pIn2); - u.az.p2 = (int)pIn2->u.i; - /* The u.az.p2 value always comes from a prior OP_CreateTable opcode and - ** that opcode will always set the u.az.p2 value to 2 or more or else fail. + p2 = (int)pIn2->u.i; + /* The p2 value always comes from a prior OP_CreateTable opcode and + ** that opcode will always set the p2 value to 2 or more or else fail. ** If there were a failure, the prepared statement would have halted ** before reaching this instruction. */ - if( NEVER(u.az.p2<2) ) { + if( NEVER(p2<2) ) { rc = SQLITE_CORRUPT_BKPT; goto abort_due_to_error; } } if( pOp->p4type==P4_KEYINFO ){ - u.az.pKeyInfo = pOp->p4.pKeyInfo; - assert( u.az.pKeyInfo->enc==ENC(db) ); - assert( u.az.pKeyInfo->db==db ); - u.az.nField = u.az.pKeyInfo->nField+u.az.pKeyInfo->nXField; + pKeyInfo = pOp->p4.pKeyInfo; + assert( pKeyInfo->enc==ENC(db) ); + assert( pKeyInfo->db==db ); + nField = pKeyInfo->nField+pKeyInfo->nXField; }else if( pOp->p4type==P4_INT32 ){ - u.az.nField = pOp->p4.i; + nField = pOp->p4.i; } assert( pOp->p1>=0 ); - assert( u.az.nField>=0 ); - testcase( u.az.nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ - u.az.pCur = allocateCursor(p, pOp->p1, u.az.nField, u.az.iDb, 1); - if( u.az.pCur==0 ) goto no_mem; - u.az.pCur->nullRow = 1; - u.az.pCur->isOrdered = 1; - rc = sqlite3BtreeCursor(u.az.pX, u.az.p2, u.az.wrFlag, u.az.pKeyInfo, u.az.pCur->pCursor); - u.az.pCur->pKeyInfo = u.az.pKeyInfo; + assert( nField>=0 ); + testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ + pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); + if( pCur==0 ) goto no_mem; + pCur->nullRow = 1; + pCur->isOrdered = 1; + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); + pCur->pKeyInfo = pKeyInfo; assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); - sqlite3BtreeCursorHints(u.az.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); + sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); /* Since it performs no memory allocation or IO, the only value that ** sqlite3BtreeCursor() may return is SQLITE_OK. */ @@ -69863,8 +70380,8 @@ case OP_OpenWrite: { /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has - ** since moved into the btree layer. */ - u.az.pCur->isTable = pOp->p4type!=P4_KEYINFO; + ** since moved into the btree layer. */ + pCur->isTable = pOp->p4type!=P4_KEYINFO; break; } @@ -69896,12 +70413,10 @@ case OP_OpenWrite: { */ case OP_OpenAutoindex: case OP_OpenEphemeral: { -#if 0 /* local variables moved into u.ba */ VdbeCursor *pCx; KeyInfo *pKeyInfo; -#endif /* local variables moved into u.ba */ - static const int vfsFlags = + static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | @@ -69909,13 +70424,13 @@ case OP_OpenEphemeral: { SQLITE_OPEN_TRANSIENT_DB; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); - if( u.ba.pCx==0 ) goto no_mem; - u.ba.pCx->nullRow = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ba.pCx->pBt, + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(u.ba.pCx->pBt, 1); + rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); } if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling @@ -69923,57 +70438,54 @@ case OP_OpenEphemeral: { ** opening it. If a transient table is required, just use the ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ - if( (u.ba.pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ + if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(u.ba.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); + rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); - assert( u.ba.pKeyInfo->db==db ); - assert( u.ba.pKeyInfo->enc==ENC(db) ); - u.ba.pCx->pKeyInfo = u.ba.pKeyInfo; - rc = sqlite3BtreeCursor(u.ba.pCx->pBt, pgno, 1, u.ba.pKeyInfo, u.ba.pCx->pCursor); + assert( pKeyInfo->db==db ); + assert( pKeyInfo->enc==ENC(db) ); + pCx->pKeyInfo = pKeyInfo; + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor); } - u.ba.pCx->isTable = 0; + pCx->isTable = 0; }else{ - rc = sqlite3BtreeCursor(u.ba.pCx->pBt, MASTER_ROOT, 1, 0, u.ba.pCx->pCursor); - u.ba.pCx->isTable = 1; + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); + pCx->isTable = 1; } } - u.ba.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); + pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); break; } -/* Opcode: SorterOpen P1 * * P4 * +/* Opcode: SorterOpen P1 P2 * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ case OP_SorterOpen: { -#if 0 /* local variables moved into u.bb */ VdbeCursor *pCx; -#endif /* local variables moved into u.bb */ assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); - if( u.bb.pCx==0 ) goto no_mem; - u.bb.pCx->pKeyInfo = pOp->p4.pKeyInfo; - assert( u.bb.pCx->pKeyInfo->db==db ); - assert( u.bb.pCx->pKeyInfo->enc==ENC(db) ); - rc = sqlite3VdbeSorterInit(db, u.bb.pCx); + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); + if( pCx==0 ) goto no_mem; + pCx->pKeyInfo = pOp->p4.pKeyInfo; + assert( pCx->pKeyInfo->db==db ); + assert( pCx->pKeyInfo->enc==ENC(db) ); + rc = sqlite3VdbeSorterInit(db, pCx); break; } -/* Opcode: OpenPseudo P1 P2 P3 * P5 -** Synopsis: content in r[P2@P3] +/* Opcode: OpenPseudo P1 P2 P3 * * +** Synopsis: P3 columns in r[P2] ** ** Open a new cursor that points to a fake table that contains a single -** row of data. The content of that one row in the content of memory -** register P2 when P5==0. In other words, cursor P1 becomes an alias for the -** MEM_Blob content contained in register P2. When P5==1, then the -** row is represented by P3 consecutive registers beginning with P2. +** row of data. The content of that one row is the content of memory +** register P2. In other words, cursor P1 becomes an alias for the +** MEM_Blob content contained in register P2. ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into @@ -69984,18 +70496,16 @@ case OP_SorterOpen: { ** the pseudo-table. */ case OP_OpenPseudo: { -#if 0 /* local variables moved into u.bc */ VdbeCursor *pCx; -#endif /* local variables moved into u.bc */ assert( pOp->p1>=0 ); assert( pOp->p3>=0 ); - u.bc.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); - if( u.bc.pCx==0 ) goto no_mem; - u.bc.pCx->nullRow = 1; - u.bc.pCx->pseudoTableReg = pOp->p2; - u.bc.pCx->isTable = 1; - u.bc.pCx->multiPseudo = pOp->p5; + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + pCx->pseudoTableReg = pOp->p2; + pCx->isTable = 1; + assert( pOp->p5==0 ); break; } @@ -70067,39 +70577,37 @@ case OP_Close: { ** ** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt */ -case OP_SeekLt: /* jump, in3 */ -case OP_SeekLe: /* jump, in3 */ -case OP_SeekGe: /* jump, in3 */ -case OP_SeekGt: { /* jump, in3 */ -#if 0 /* local variables moved into u.bd */ +case OP_SeekLT: /* jump, in3 */ +case OP_SeekLE: /* jump, in3 */ +case OP_SeekGE: /* jump, in3 */ +case OP_SeekGT: { /* jump, in3 */ int res; int oc; VdbeCursor *pC; UnpackedRecord r; int nField; i64 iKey; /* The rowid we are to seek to */ -#endif /* local variables moved into u.bd */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p2!=0 ); - u.bd.pC = p->apCsr[pOp->p1]; - assert( u.bd.pC!=0 ); - assert( u.bd.pC->pseudoTableReg==0 ); - assert( OP_SeekLe == OP_SeekLt+1 ); - assert( OP_SeekGe == OP_SeekLt+2 ); - assert( OP_SeekGt == OP_SeekLt+3 ); - assert( u.bd.pC->isOrdered ); - assert( u.bd.pC->pCursor!=0 ); - u.bd.oc = pOp->opcode; - u.bd.pC->nullRow = 0; - if( u.bd.pC->isTable ){ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pseudoTableReg==0 ); + assert( OP_SeekLE == OP_SeekLT+1 ); + assert( OP_SeekGE == OP_SeekLT+2 ); + assert( OP_SeekGT == OP_SeekLT+3 ); + assert( pC->isOrdered ); + assert( pC->pCursor!=0 ); + oc = pOp->opcode; + pC->nullRow = 0; + if( pC->isTable ){ /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so covert it. */ pIn3 = &aMem[pOp->p3]; applyNumericAffinity(pIn3); - u.bd.iKey = sqlite3VdbeIntValue(pIn3); - u.bd.pC->rowidIsValid = 0; + iKey = sqlite3VdbeIntValue(pIn3); + pC->rowidIsValid = 0; /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ @@ -70107,100 +70615,103 @@ case OP_SeekGt: { /* jump, in3 */ if( (pIn3->flags & MEM_Real)==0 ){ /* If the P3 value cannot be converted into any kind of a number, ** then the seek is not possible, so jump to P2 */ - pc = pOp->p2 - 1; + pc = pOp->p2 - 1; VdbeBranchTaken(1,2); break; } - /* If the approximation u.bd.iKey is larger than the actual real search + /* If the approximation iKey is larger than the actual real search ** term, substitute >= for > and < for <=. e.g. if the search term ** is 4.9 and the integer approximation 5: ** ** (x > 4.9) -> (x >= 5) ** (x <= 4.9) -> (x < 5) */ - if( pIn3->r<(double)u.bd.iKey ){ - assert( OP_SeekGe==(OP_SeekGt-1) ); - assert( OP_SeekLt==(OP_SeekLe-1) ); - assert( (OP_SeekLe & 0x0001)==(OP_SeekGt & 0x0001) ); - if( (u.bd.oc & 0x0001)==(OP_SeekGt & 0x0001) ) u.bd.oc--; + if( pIn3->r<(double)iKey ){ + assert( OP_SeekGE==(OP_SeekGT-1) ); + assert( OP_SeekLT==(OP_SeekLE-1) ); + assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; } - /* If the approximation u.bd.iKey is smaller than the actual real search + /* If the approximation iKey is smaller than the actual real search ** term, substitute <= for < and > for >=. */ - else if( pIn3->r>(double)u.bd.iKey ){ - assert( OP_SeekLe==(OP_SeekLt+1) ); - assert( OP_SeekGt==(OP_SeekGe+1) ); - assert( (OP_SeekLt & 0x0001)==(OP_SeekGe & 0x0001) ); - if( (u.bd.oc & 0x0001)==(OP_SeekLt & 0x0001) ) u.bd.oc++; + else if( pIn3->r>(double)iKey ){ + assert( OP_SeekLE==(OP_SeekLT+1) ); + assert( OP_SeekGT==(OP_SeekGE+1) ); + assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } - } - rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, 0, (u64)u.bd.iKey, 0, &u.bd.res); + } + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - if( u.bd.res==0 ){ - u.bd.pC->rowidIsValid = 1; - u.bd.pC->lastRowid = u.bd.iKey; + if( res==0 ){ + pC->rowidIsValid = 1; + pC->lastRowid = iKey; } }else{ - u.bd.nField = pOp->p4.i; + nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); - assert( u.bd.nField>0 ); - u.bd.r.pKeyInfo = u.bd.pC->pKeyInfo; - u.bd.r.nField = (u16)u.bd.nField; + assert( nField>0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)nField; /* The next line of code computes as follows, only faster: - ** if( u.bd.oc==OP_SeekGt || u.bd.oc==OP_SeekLe ){ - ** u.bd.r.flags = UNPACKED_INCRKEY; + ** if( oc==OP_SeekGT || oc==OP_SeekLE ){ + ** r.default_rc = -1; ** }else{ - ** u.bd.r.flags = 0; + ** r.default_rc = +1; ** } */ - u.bd.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bd.oc - OP_SeekLt))); - assert( u.bd.oc!=OP_SeekGt || u.bd.r.flags==UNPACKED_INCRKEY ); - assert( u.bd.oc!=OP_SeekLe || u.bd.r.flags==UNPACKED_INCRKEY ); - assert( u.bd.oc!=OP_SeekGe || u.bd.r.flags==0 ); - assert( u.bd.oc!=OP_SeekLt || u.bd.r.flags==0 ); + r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1); + assert( oc!=OP_SeekGT || r.default_rc==-1 ); + assert( oc!=OP_SeekLE || r.default_rc==-1 ); + assert( oc!=OP_SeekGE || r.default_rc==+1 ); + assert( oc!=OP_SeekLT || r.default_rc==+1 ); - u.bd.r.aMem = &aMem[pOp->p3]; + r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG - { int i; for(i=0; ipCursor, &u.bd.r, 0, 0, &u.bd.res); + ExpandBlob(r.aMem); + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - u.bd.pC->rowidIsValid = 0; + pC->rowidIsValid = 0; } - u.bd.pC->deferredMoveto = 0; - u.bd.pC->cacheStatus = CACHE_STALE; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; #ifdef SQLITE_TEST sqlite3_search_count++; #endif - if( u.bd.oc>=OP_SeekGe ){ assert( u.bd.oc==OP_SeekGe || u.bd.oc==OP_SeekGt ); - if( u.bd.res<0 || (u.bd.res==0 && u.bd.oc==OP_SeekGt) ){ - rc = sqlite3BtreeNext(u.bd.pC->pCursor, &u.bd.res); + if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); + if( res<0 || (res==0 && oc==OP_SeekGT) ){ + res = 0; + rc = sqlite3BtreeNext(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; - u.bd.pC->rowidIsValid = 0; + pC->rowidIsValid = 0; }else{ - u.bd.res = 0; + res = 0; } }else{ - assert( u.bd.oc==OP_SeekLt || u.bd.oc==OP_SeekLe ); - if( u.bd.res>0 || (u.bd.res==0 && u.bd.oc==OP_SeekLt) ){ - rc = sqlite3BtreePrevious(u.bd.pC->pCursor, &u.bd.res); + assert( oc==OP_SeekLT || oc==OP_SeekLE ); + if( res>0 || (res==0 && oc==OP_SeekLT) ){ + res = 0; + rc = sqlite3BtreePrevious(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; - u.bd.pC->rowidIsValid = 0; + pC->rowidIsValid = 0; }else{ - /* u.bd.res might be negative because the table is empty. Check to + /* res might be negative because the table is empty. Check to ** see if this is the case. */ - u.bd.res = sqlite3BtreeEof(u.bd.pC->pCursor); + res = sqlite3BtreeEof(pC->pCursor); } } assert( pOp->p2>0 ); - if( u.bd.res ){ + VdbeBranchTaken(res!=0,2); + if( res ){ pc = pOp->p2 - 1; } break; @@ -70217,20 +70728,18 @@ case OP_SeekGt: { /* jump, in3 */ ** occur, no unnecessary I/O happens. */ case OP_Seek: { /* in2 */ -#if 0 /* local variables moved into u.be */ VdbeCursor *pC; -#endif /* local variables moved into u.be */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.be.pC = p->apCsr[pOp->p1]; - assert( u.be.pC!=0 ); - assert( u.be.pC->pCursor!=0 ); - assert( u.be.pC->isTable ); - u.be.pC->nullRow = 0; + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); + assert( pC->isTable ); + pC->nullRow = 0; pIn2 = &aMem[pOp->p2]; - u.be.pC->movetoTarget = sqlite3VdbeIntValue(pIn2); - u.be.pC->rowidIsValid = 0; - u.be.pC->deferredMoveto = 1; + pC->movetoTarget = sqlite3VdbeIntValue(pIn2); + pC->rowidIsValid = 0; + pC->deferredMoveto = 1; break; } @@ -70285,7 +70794,6 @@ case OP_Seek: { /* in2 */ case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ -#if 0 /* local variables moved into u.bf */ int alreadyExists; int ii; VdbeCursor *pC; @@ -70294,72 +70802,70 @@ case OP_Found: { /* jump, in3 */ UnpackedRecord *pIdxKey; UnpackedRecord r; char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7]; -#endif /* local variables moved into u.bf */ #ifdef SQLITE_TEST if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; #endif - u.bf.alreadyExists = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p4type==P4_INT32 ); - u.bf.pC = p->apCsr[pOp->p1]; - assert( u.bf.pC!=0 ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); pIn3 = &aMem[pOp->p3]; - assert( u.bf.pC->pCursor!=0 ); - assert( u.bf.pC->isTable==0 ); + assert( pC->pCursor!=0 ); + assert( pC->isTable==0 ); + pFree = 0; /* Not needed. Only used to suppress a compiler warning. */ if( pOp->p4.i>0 ){ - u.bf.r.pKeyInfo = u.bf.pC->pKeyInfo; - u.bf.r.nField = (u16)pOp->p4.i; - u.bf.r.aMem = pIn3; + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p4.i; + r.aMem = pIn3; + for(ii=0; iip3+i, &u.bf.r.aMem[i]); - } - } + if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]); #endif - u.bf.r.flags = UNPACKED_PREFIX_MATCH; - u.bf.pIdxKey = &u.bf.r; + } + pIdxKey = &r; }else{ - u.bf.pIdxKey = sqlite3VdbeAllocUnpackedRecord( - u.bf.pC->pKeyInfo, u.bf.aTempRec, sizeof(u.bf.aTempRec), &u.bf.pFree - ); - if( u.bf.pIdxKey==0 ) goto no_mem; + pIdxKey = sqlite3VdbeAllocUnpackedRecord( + pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree + ); + if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ - sqlite3VdbeRecordUnpack(u.bf.pC->pKeyInfo, pIn3->n, pIn3->z, u.bf.pIdxKey); - u.bf.pIdxKey->flags |= UNPACKED_PREFIX_MATCH; + sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } + pIdxKey->default_rc = 0; if( pOp->opcode==OP_NoConflict ){ /* For the OP_NoConflict opcode, take the jump if any of the ** input fields are NULL, since any key with a NULL will not ** conflict */ - for(u.bf.ii=0; u.bf.iip2 - 1; + for(ii=0; iip2 - 1; VdbeBranchTaken(1,2); break; } } } - rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, u.bf.pIdxKey, 0, 0, &u.bf.res); + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); if( pOp->p4.i==0 ){ - sqlite3DbFree(db, u.bf.pFree); + sqlite3DbFree(db, pFree); } if( rc!=SQLITE_OK ){ break; } - u.bf.pC->seekResult = u.bf.res; - u.bf.alreadyExists = (u.bf.res==0); - u.bf.pC->nullRow = 1-u.bf.alreadyExists; - u.bf.pC->deferredMoveto = 0; - u.bf.pC->cacheStatus = CACHE_STALE; + pC->seekResult = res; + alreadyExists = (res==0); + pC->nullRow = 1-alreadyExists; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ - if( u.bf.alreadyExists ) pc = pOp->p2 - 1; + VdbeBranchTaken(alreadyExists!=0,2); + if( alreadyExists ) pc = pOp->p2 - 1; }else{ - if( !u.bf.alreadyExists ) pc = pOp->p2 - 1; + VdbeBranchTaken(alreadyExists==0,2); + if( !alreadyExists ) pc = pOp->p2 - 1; } break; } @@ -70379,35 +70885,34 @@ case OP_Found: { /* jump, in3 */ ** See also: Found, NotFound, NoConflict */ case OP_NotExists: { /* jump, in3 */ -#if 0 /* local variables moved into u.bg */ VdbeCursor *pC; BtCursor *pCrsr; int res; u64 iKey; -#endif /* local variables moved into u.bg */ pIn3 = &aMem[pOp->p3]; assert( pIn3->flags & MEM_Int ); assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bg.pC = p->apCsr[pOp->p1]; - assert( u.bg.pC!=0 ); - assert( u.bg.pC->isTable ); - assert( u.bg.pC->pseudoTableReg==0 ); - u.bg.pCrsr = u.bg.pC->pCursor; - assert( u.bg.pCrsr!=0 ); - u.bg.res = 0; - u.bg.iKey = pIn3->u.i; - rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res); - u.bg.pC->lastRowid = pIn3->u.i; - u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0; - u.bg.pC->nullRow = 0; - u.bg.pC->cacheStatus = CACHE_STALE; - u.bg.pC->deferredMoveto = 0; - if( u.bg.res!=0 ){ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->isTable ); + assert( pC->pseudoTableReg==0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); + res = 0; + iKey = pIn3->u.i; + rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); + pC->lastRowid = pIn3->u.i; + pC->rowidIsValid = res==0 ?1:0; + pC->nullRow = 0; + pC->cacheStatus = CACHE_STALE; + pC->deferredMoveto = 0; + VdbeBranchTaken(res!=0,2); + if( res!=0 ){ pc = pOp->p2 - 1; - assert( u.bg.pC->rowidIsValid==0 ); + assert( pC->rowidIsValid==0 ); } - u.bg.pC->seekResult = u.bg.res; + pC->seekResult = res; break; } @@ -70443,21 +70948,19 @@ case OP_Sequence: { /* out2-prerelease */ ** AUTOINCREMENT feature. */ case OP_NewRowid: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bh */ i64 v; /* The new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */ int res; /* Result of an sqlite3BtreeLast() */ int cnt; /* Counter to limit the number of searches */ Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ VdbeFrame *pFrame; /* Root frame of VDBE */ -#endif /* local variables moved into u.bh */ - u.bh.v = 0; - u.bh.res = 0; + v = 0; + res = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bh.pC = p->apCsr[pOp->p1]; - assert( u.bh.pC!=0 ); - if( NEVER(u.bh.pC->pCursor==0) ){ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + if( NEVER(pC->pCursor==0) ){ /* The zero initialization above is all that is needed */ }else{ /* The next rowid or record number (different terms for the same @@ -70473,7 +70976,7 @@ case OP_NewRowid: { /* out2-prerelease */ ** succeeded. If the random rowid does exist, we select a new one ** and try again, up to 100 times. */ - assert( u.bh.pC->isTable ); + assert( pC->isTable ); #ifdef SQLITE_32BIT_ROWID # define MAX_ROWID 0x7fffffff @@ -70485,61 +70988,56 @@ case OP_NewRowid: { /* out2-prerelease */ # define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) #endif - if( !u.bh.pC->useRandomRowid ){ - u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor); - if( u.bh.v==0 ){ - rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( u.bh.res ){ - u.bh.v = 1; /* IMP: R-61914-48074 */ + if( !pC->useRandomRowid ){ + rc = sqlite3BtreeLast(pC->pCursor, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res ){ + v = 1; /* IMP: R-61914-48074 */ + }else{ + assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); + rc = sqlite3BtreeKeySize(pC->pCursor, &v); + assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + if( v>=MAX_ROWID ){ + pC->useRandomRowid = 1; }else{ - assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) ); - rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v); - assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ - if( u.bh.v>=MAX_ROWID ){ - u.bh.pC->useRandomRowid = 1; - }else{ - u.bh.v++; /* IMP: R-29538-34987 */ - } + v++; /* IMP: R-29538-34987 */ } } + } #ifndef SQLITE_OMIT_AUTOINCREMENT - if( pOp->p3 ){ + if( pOp->p3 ){ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3>0 ); + if( p->pFrame ){ + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3>0 ); - if( p->pFrame ){ - for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent); - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=u.bh.pFrame->nMem ); - u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3]; - }else{ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=(p->nMem-p->nCursor) ); - u.bh.pMem = &aMem[pOp->p3]; - memAboutToChange(p, u.bh.pMem); - } - assert( memIsValid(u.bh.pMem) ); - - REGISTER_TRACE(pOp->p3, u.bh.pMem); - sqlite3VdbeMemIntegerify(u.bh.pMem); - assert( (u.bh.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ - if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ - goto abort_due_to_error; - } - if( u.bh.vu.i+1 ){ - u.bh.v = u.bh.pMem->u.i + 1; - } - u.bh.pMem->u.i = u.bh.v; + assert( pOp->p3<=pFrame->nMem ); + pMem = &pFrame->aMem[pOp->p3]; + }else{ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pMem = &aMem[pOp->p3]; + memAboutToChange(p, pMem); } -#endif + assert( memIsValid(pMem) ); - sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.vp3, pMem); + sqlite3VdbeMemIntegerify(pMem); + assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ + rc = SQLITE_FULL; /* IMP: R-12275-61338 */ + goto abort_due_to_error; + } + if( vu.i+1 ){ + v = pMem->u.i + 1; + } + pMem->u.i = v; } - if( u.bh.pC->useRandomRowid ){ +#endif + if( pC->useRandomRowid ){ /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the ** largest possible integer (9223372036854775807) then the database ** engine starts picking positive candidate ROWIDs at random until @@ -70547,35 +71045,35 @@ case OP_NewRowid: { /* out2-prerelease */ assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is ** an AUTOINCREMENT table. */ /* on the first attempt, simply do one more than previous */ - u.bh.v = lastRowid; - u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ - u.bh.v++; /* ensure non-zero */ - u.bh.cnt = 0; - while( ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v, - 0, &u.bh.res))==SQLITE_OK) - && (u.bh.res==0) - && (++u.bh.cnt<100)){ + v = lastRowid; + v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ + v++; /* ensure non-zero */ + cnt = 0; + while( ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v, + 0, &res))==SQLITE_OK) + && (res==0) + && (++cnt<100)){ /* collision - try another random rowid */ - sqlite3_randomness(sizeof(u.bh.v), &u.bh.v); - if( u.bh.cnt<5 ){ + sqlite3_randomness(sizeof(v), &v); + if( cnt<5 ){ /* try "small" random rowids for the initial attempts */ - u.bh.v &= 0xffffff; + v &= 0xffffff; }else{ - u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ + v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ } - u.bh.v++; /* ensure non-zero */ + v++; /* ensure non-zero */ } - if( rc==SQLITE_OK && u.bh.res==0 ){ + if( rc==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; /* IMP: R-38219-53002 */ goto abort_due_to_error; } - assert( u.bh.v>0 ); /* EV: R-40812-03570 */ + assert( v>0 ); /* EV: R-40812-03570 */ } - u.bh.pC->rowidIsValid = 0; - u.bh.pC->deferredMoveto = 0; - u.bh.pC->cacheStatus = CACHE_STALE; + pC->rowidIsValid = 0; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; } - pOut->u.i = u.bh.v; + pOut->u.i = v; break; } @@ -70627,7 +71125,6 @@ case OP_NewRowid: { /* out2-prerelease */ */ case OP_Insert: case OP_InsertInt: { -#if 0 /* local variables moved into u.bi */ Mem *pData; /* MEM cell holding data for the record to be inserted */ Mem *pKey; /* MEM cell holding key for the record */ i64 iKey; /* The integer ROWID or key for the record to be inserted */ @@ -70637,60 +71134,58 @@ case OP_InsertInt: { const char *zDb; /* database name - used by the update hook */ const char *zTbl; /* Table name - used by the opdate hook */ int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ -#endif /* local variables moved into u.bi */ - u.bi.pData = &aMem[pOp->p2]; + pData = &aMem[pOp->p2]; assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( memIsValid(u.bi.pData) ); - u.bi.pC = p->apCsr[pOp->p1]; - assert( u.bi.pC!=0 ); - assert( u.bi.pC->pCursor!=0 ); - assert( u.bi.pC->pseudoTableReg==0 ); - assert( u.bi.pC->isTable ); - REGISTER_TRACE(pOp->p2, u.bi.pData); + assert( memIsValid(pData) ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); + assert( pC->pseudoTableReg==0 ); + assert( pC->isTable ); + REGISTER_TRACE(pOp->p2, pData); if( pOp->opcode==OP_Insert ){ - u.bi.pKey = &aMem[pOp->p3]; - assert( u.bi.pKey->flags & MEM_Int ); - assert( memIsValid(u.bi.pKey) ); - REGISTER_TRACE(pOp->p3, u.bi.pKey); - u.bi.iKey = u.bi.pKey->u.i; + pKey = &aMem[pOp->p3]; + assert( pKey->flags & MEM_Int ); + assert( memIsValid(pKey) ); + REGISTER_TRACE(pOp->p3, pKey); + iKey = pKey->u.i; }else{ assert( pOp->opcode==OP_InsertInt ); - u.bi.iKey = pOp->p3; + iKey = pOp->p3; } if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey; - if( u.bi.pData->flags & MEM_Null ){ - u.bi.pData->z = 0; - u.bi.pData->n = 0; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey; + if( pData->flags & MEM_Null ){ + pData->z = 0; + pData->n = 0; }else{ - assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) ); + assert( pData->flags & (MEM_Blob|MEM_Str) ); } - u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0); - if( u.bi.pData->flags & MEM_Zero ){ - u.bi.nZero = u.bi.pData->u.nZero; + seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); + if( pData->flags & MEM_Zero ){ + nZero = pData->u.nZero; }else{ - u.bi.nZero = 0; + nZero = 0; } - sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0); - rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey, - u.bi.pData->z, u.bi.pData->n, u.bi.nZero, - (pOp->p5 & OPFLAG_APPEND)!=0, u.bi.seekResult + rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, + pData->z, pData->n, nZero, + (pOp->p5 & OPFLAG_APPEND)!=0, seekResult ); - u.bi.pC->rowidIsValid = 0; - u.bi.pC->deferredMoveto = 0; - u.bi.pC->cacheStatus = CACHE_STALE; + pC->rowidIsValid = 0; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - u.bi.zDb = db->aDb[u.bi.pC->iDb].zName; - u.bi.zTbl = pOp->p4.z; - u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); - assert( u.bi.pC->isTable ); - db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey); - assert( u.bi.pC->iDb>=0 ); + zDb = db->aDb[pC->iDb].zName; + zTbl = pOp->p4.z; + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + assert( pC->isTable ); + db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); + assert( pC->iDb>=0 ); } break; } @@ -70716,37 +71211,34 @@ case OP_InsertInt: { ** using OP_NotFound prior to invoking this opcode. */ case OP_Delete: { -#if 0 /* local variables moved into u.bj */ i64 iKey; VdbeCursor *pC; -#endif /* local variables moved into u.bj */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bj.pC = p->apCsr[pOp->p1]; - assert( u.bj.pC!=0 ); - assert( u.bj.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ - u.bj.iKey = u.bj.pC->lastRowid; /* Only used for the update hook */ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + iKey = pC->lastRowid; /* Only used for the update hook */ /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or ** OP_Column on the same table without any intervening operations that - ** might move or invalidate the cursor. Hence cursor u.bj.pC is always pointing + ** might move or invalidate the cursor. Hence cursor pC is always pointing ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation ** below is always a no-op and cannot fail. We will run it anyhow, though, ** to guard against future changes to the code generator. **/ - assert( u.bj.pC->deferredMoveto==0 ); - rc = sqlite3VdbeCursorMoveto(u.bj.pC); + assert( pC->deferredMoveto==0 ); + rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0); - rc = sqlite3BtreeDelete(u.bj.pC->pCursor); - u.bj.pC->cacheStatus = CACHE_STALE; + rc = sqlite3BtreeDelete(pC->pCursor); + pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && u.bj.pC->isTable ){ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, - db->aDb[u.bj.pC->iDb].zName, pOp->p4.z, u.bj.iKey); - assert( u.bj.pC->iDb>=0 ); + db->aDb[pC->iDb].zName, pOp->p4.z, iKey); + assert( pC->iDb>=0 ); } if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; @@ -70780,19 +71272,18 @@ case OP_ResetCount: { ** each other. Jump to P2 if they are different. */ case OP_SorterCompare: { -#if 0 /* local variables moved into u.bk */ VdbeCursor *pC; int res; int nIgnore; -#endif /* local variables moved into u.bk */ - u.bk.pC = p->apCsr[pOp->p1]; - assert( isSorter(u.bk.pC) ); + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); assert( pOp->p4type==P4_INT32 ); pIn3 = &aMem[pOp->p3]; - u.bk.nIgnore = pOp->p4.i; - rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, u.bk.nIgnore, &u.bk.res); - if( u.bk.res ){ + nIgnore = pOp->p4.i; + rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res); + VdbeBranchTaken(res!=0,2); + if( res ){ pc = pOp->p2-1; } break; @@ -70804,14 +71295,12 @@ case OP_SorterCompare: { ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { -#if 0 /* local variables moved into u.bl */ VdbeCursor *pC; -#endif /* local variables moved into u.bl */ pOut = &aMem[pOp->p2]; - u.bl.pC = p->apCsr[pOp->p1]; - assert( isSorter(u.bl.pC) ); - rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut); + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); + rc = sqlite3VdbeSorterRowkey(pC, pOut); break; } @@ -70831,7 +71320,7 @@ case OP_SorterData: { ** ** Write into register P2 the complete row key for cursor P1. ** There is no interpretation of the data. -** The key is copied onto the P3 register exactly as +** The key is copied onto the P2 register exactly as ** it is found in the database file. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) @@ -70839,62 +71328,60 @@ case OP_SorterData: { */ case OP_RowKey: case OP_RowData: { -#if 0 /* local variables moved into u.bm */ VdbeCursor *pC; BtCursor *pCrsr; u32 n; i64 n64; -#endif /* local variables moved into u.bm */ pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bm.pC = p->apCsr[pOp->p1]; - assert( isSorter(u.bm.pC)==0 ); - assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData ); - assert( u.bm.pC->isTable==0 || pOp->opcode==OP_RowData ); - assert( u.bm.pC!=0 ); - assert( u.bm.pC->nullRow==0 ); - assert( u.bm.pC->pseudoTableReg==0 ); - assert( u.bm.pC->pCursor!=0 ); - u.bm.pCrsr = u.bm.pC->pCursor; - assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) ); + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC)==0 ); + assert( pC->isTable || pOp->opcode!=OP_RowData ); + assert( pC->isTable==0 || pOp->opcode==OP_RowData ); + assert( pC!=0 ); + assert( pC->nullRow==0 ); + assert( pC->pseudoTableReg==0 ); + assert( pC->pCursor!=0 ); + pCrsr = pC->pCursor; + assert( sqlite3BtreeCursorIsValid(pCrsr) ); /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or ** OP_Rewind/Op_Next with no intervening instructions that might invalidate ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always ** a no-op and can never fail. But we leave it in place as a safety. */ - assert( u.bm.pC->deferredMoveto==0 ); - rc = sqlite3VdbeCursorMoveto(u.bm.pC); + assert( pC->deferredMoveto==0 ); + rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - if( u.bm.pC->isTable==0 ){ - assert( !u.bm.pC->isTable ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64); + if( pC->isTable==0 ){ + assert( !pC->isTable ); + VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64); assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - u.bm.n = (u32)u.bm.n64; + n = (u32)n64; }else{ - VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n); + VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n); assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } } - if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){ + if( sqlite3VdbeMemGrow(pOut, n, 0) ){ goto no_mem; } - pOut->n = u.bm.n; + pOut->n = n; MemSetTypeFlag(pOut, MEM_Blob); - if( u.bm.pC->isTable==0 ){ - rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z); + if( pC->isTable==0 ){ + rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); }else{ - rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z); + rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); } pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); @@ -70913,42 +71400,40 @@ case OP_RowData: { ** one opcode now works for both table types. */ case OP_Rowid: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bn */ VdbeCursor *pC; i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; -#endif /* local variables moved into u.bn */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bn.pC = p->apCsr[pOp->p1]; - assert( u.bn.pC!=0 ); - assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow ); - if( u.bn.pC->nullRow ){ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->pseudoTableReg==0 || pC->nullRow ); + if( pC->nullRow ){ pOut->flags = MEM_Null; break; - }else if( u.bn.pC->deferredMoveto ){ - u.bn.v = u.bn.pC->movetoTarget; + }else if( pC->deferredMoveto ){ + v = pC->movetoTarget; #ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( u.bn.pC->pVtabCursor ){ - u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab; - u.bn.pModule = u.bn.pVtab->pModule; - assert( u.bn.pModule->xRowid ); - rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v); - sqlite3VtabImportErrmsg(p, u.bn.pVtab); + }else if( pC->pVtabCursor ){ + pVtab = pC->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xRowid ); + rc = pModule->xRowid(pC->pVtabCursor, &v); + sqlite3VtabImportErrmsg(p, pVtab); #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ - assert( u.bn.pC->pCursor!=0 ); - rc = sqlite3VdbeCursorMoveto(u.bn.pC); + assert( pC->pCursor!=0 ); + rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; - if( u.bn.pC->rowidIsValid ){ - u.bn.v = u.bn.pC->lastRowid; + if( pC->rowidIsValid ){ + v = pC->lastRowid; }else{ - rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v); + rc = sqlite3BtreeKeySize(pC->pCursor, &v); assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */ } } - pOut->u.i = u.bn.v; + pOut->u.i = v; break; } @@ -70959,19 +71444,16 @@ case OP_Rowid: { /* out2-prerelease */ ** write a NULL. */ case OP_NullRow: { -#if 0 /* local variables moved into u.bo */ VdbeCursor *pC; -#endif /* local variables moved into u.bo */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bo.pC = p->apCsr[pOp->p1]; - assert( u.bo.pC!=0 ); - u.bo.pC->nullRow = 1; - u.bo.pC->rowidIsValid = 0; - u.bo.pC->cacheStatus = CACHE_STALE; - assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor ); - if( u.bo.pC->pCursor ){ - sqlite3BtreeClearCursor(u.bo.pC->pCursor); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pC->nullRow = 1; + pC->rowidIsValid = 0; + pC->cacheStatus = CACHE_STALE; + if( pC->pCursor ){ + sqlite3BtreeClearCursor(pC->pCursor); } break; } @@ -70985,25 +71467,24 @@ case OP_NullRow: { ** to the following instruction. */ case OP_Last: { /* jump */ -#if 0 /* local variables moved into u.bp */ VdbeCursor *pC; BtCursor *pCrsr; int res; -#endif /* local variables moved into u.bp */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bp.pC = p->apCsr[pOp->p1]; - assert( u.bp.pC!=0 ); - u.bp.pCrsr = u.bp.pC->pCursor; - u.bp.res = 0; - assert( u.bp.pCrsr!=0 ); - rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res); - u.bp.pC->nullRow = (u8)u.bp.res; - u.bp.pC->deferredMoveto = 0; - u.bp.pC->rowidIsValid = 0; - u.bp.pC->cacheStatus = CACHE_STALE; - if( pOp->p2>0 && u.bp.res ){ - pc = pOp->p2 - 1; + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + res = 0; + assert( pCrsr!=0 ); + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->rowidIsValid = 0; + pC->cacheStatus = CACHE_STALE; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) pc = pOp->p2 - 1; } break; } @@ -71039,36 +71520,35 @@ case OP_Sort: { /* jump */ ** to the following instruction. */ case OP_Rewind: { /* jump */ -#if 0 /* local variables moved into u.bq */ VdbeCursor *pC; BtCursor *pCrsr; int res; -#endif /* local variables moved into u.bq */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bq.pC = p->apCsr[pOp->p1]; - assert( u.bq.pC!=0 ); - assert( isSorter(u.bq.pC)==(pOp->opcode==OP_SorterSort) ); - u.bq.res = 1; - if( isSorter(u.bq.pC) ){ - rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res); - }else{ - u.bq.pCrsr = u.bq.pC->pCursor; - assert( u.bq.pCrsr ); - rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res); - u.bq.pC->deferredMoveto = 0; - u.bq.pC->cacheStatus = CACHE_STALE; - u.bq.pC->rowidIsValid = 0; - } - u.bq.pC->nullRow = (u8)u.bq.res; + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); + res = 1; + if( isSorter(pC) ){ + rc = sqlite3VdbeSorterRewind(db, pC, &res); + }else{ + pCrsr = pC->pCursor; + assert( pCrsr ); + rc = sqlite3BtreeFirst(pCrsr, &res); + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + pC->rowidIsValid = 0; + } + pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); - if( u.bq.res ){ + VdbeBranchTaken(res!=0,2); + if( res ){ pc = pOp->p2 - 1; } break; } -/* Opcode: Next P1 P2 * * P5 +/* Opcode: Next P1 P2 P3 P4 P5 ** ** Advance cursor P1 so that it points to the next key/data pair in its ** table or index. If there are no more key/value pairs then fall through @@ -71078,6 +71558,11 @@ case OP_Rewind: { /* jump */ ** The P1 cursor must be for a real table, not a pseudo-table. P1 must have ** been opened prior to this opcode or the program will segfault. ** +** The P3 value is a hint to the btree implementation. If P3==1, that +** means P1 is an SQL index and that this instruction could have been +** omitted if that index had been unique. P3 is usually 0. P3 is +** always either 0 or 1. +** ** P4 is always of type P4_ADVANCE. The function pointer points to ** sqlite3BtreeNext(). ** @@ -71086,12 +71571,12 @@ case OP_Rewind: { /* jump */ ** ** See also: Prev, NextIfOpen */ -/* Opcode: NextIfOpen P1 P2 * * P5 +/* Opcode: NextIfOpen P1 P2 P3 P4 P5 ** ** This opcode works just like OP_Next except that if cursor P1 is not ** open it behaves a no-op. */ -/* Opcode: Prev P1 P2 * * P5 +/* Opcode: Prev P1 P2 P3 P4 P5 ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through @@ -71101,26 +71586,29 @@ case OP_Rewind: { /* jump */ ** The P1 cursor must be for a real table, not a pseudo-table. If P1 is ** not open then the behavior is undefined. ** +** The P3 value is a hint to the btree implementation. If P3==1, that +** means P1 is an SQL index and that this instruction could have been +** omitted if that index had been unique. P3 is usually 0. P3 is +** always either 0 or 1. +** ** P4 is always of type P4_ADVANCE. The function pointer points to ** sqlite3BtreePrevious(). ** ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. */ -/* Opcode: PrevIfOpen P1 P2 * * P5 +/* Opcode: PrevIfOpen P1 P2 P3 P4 P5 ** ** This opcode works just like OP_Prev except that if cursor P1 is not ** open it behaves a no-op. */ case OP_SorterNext: { /* jump */ -#if 0 /* local variables moved into u.br */ VdbeCursor *pC; int res; -#endif /* local variables moved into u.br */ - u.br.pC = p->apCsr[pOp->p1]; - assert( isSorter(u.br.pC) ); - rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res); + pC = p->apCsr[pOp->p1]; + assert( isSorter(pC) ); + rc = sqlite3VdbeSorterNext(db, pC, &res); goto next_tail; case OP_PrevIfOpen: /* jump */ case OP_NextIfOpen: /* jump */ @@ -71130,28 +71618,32 @@ case OP_Prev: /* jump */ case OP_Next: /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p5aCounter) ); - u.br.pC = p->apCsr[pOp->p1]; - assert( u.br.pC!=0 ); - assert( u.br.pC->deferredMoveto==0 ); - assert( u.br.pC->pCursor ); + pC = p->apCsr[pOp->p1]; + res = pOp->p3; + assert( pC!=0 ); + assert( pC->deferredMoveto==0 ); + assert( pC->pCursor ); + assert( res==0 || (res==1 && pC->isTable==0) ); + testcase( res==1 ); assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); - rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res); + rc = pOp->p4.xAdvance(pC->pCursor, &res); next_tail: - u.br.pC->cacheStatus = CACHE_STALE; - if( u.br.res==0 ){ - u.br.pC->nullRow = 0; + pC->cacheStatus = CACHE_STALE; + VdbeBranchTaken(res==0,2); + if( res==0 ){ + pC->nullRow = 0; pc = pOp->p2 - 1; p->aCounter[pOp->p5]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif }else{ - u.br.pC->nullRow = 1; + pC->nullRow = 1; } - u.br.pC->rowidIsValid = 0; + pC->rowidIsValid = 0; goto check_for_interrupt; } @@ -71165,40 +71657,46 @@ next_tail: ** P3 is a flag that provides a hint to the b-tree layer that this ** insert is likely to be an append. ** +** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is +** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, +** then the change counter is unchanged. +** +** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have +** just done a seek to the spot where the new entry is to be inserted. +** This flag avoids doing an extra seek. +** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ case OP_SorterInsert: /* in2 */ case OP_IdxInsert: { /* in2 */ -#if 0 /* local variables moved into u.bs */ VdbeCursor *pC; BtCursor *pCrsr; int nKey; const char *zKey; -#endif /* local variables moved into u.bs */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bs.pC = p->apCsr[pOp->p1]; - assert( u.bs.pC!=0 ); - assert( isSorter(u.bs.pC)==(pOp->opcode==OP_SorterInsert) ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); pIn2 = &aMem[pOp->p2]; assert( pIn2->flags & MEM_Blob ); - u.bs.pCrsr = u.bs.pC->pCursor; + pCrsr = pC->pCursor; if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - assert( u.bs.pCrsr!=0 ); - assert( u.bs.pC->isTable==0 ); + assert( pCrsr!=0 ); + assert( pC->isTable==0 ); rc = ExpandBlob(pIn2); if( rc==SQLITE_OK ){ - if( isSorter(u.bs.pC) ){ - rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2); + if( isSorter(pC) ){ + rc = sqlite3VdbeSorterWrite(db, pC, pIn2); }else{ - u.bs.nKey = pIn2->n; - u.bs.zKey = pIn2->z; - rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3, - ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0) + nKey = pIn2->n; + zKey = pIn2->z; + rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3, + ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); - assert( u.bs.pC->deferredMoveto==0 ); - u.bs.pC->cacheStatus = CACHE_STALE; + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; } } break; @@ -71212,34 +71710,32 @@ case OP_IdxInsert: { /* in2 */ ** index opened by cursor P1. */ case OP_IdxDelete: { -#if 0 /* local variables moved into u.bt */ VdbeCursor *pC; BtCursor *pCrsr; int res; UnpackedRecord r; -#endif /* local variables moved into u.bt */ assert( pOp->p3>0 ); assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 ); assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bt.pC = p->apCsr[pOp->p1]; - assert( u.bt.pC!=0 ); - u.bt.pCrsr = u.bt.pC->pCursor; - assert( u.bt.pCrsr!=0 ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); assert( pOp->p5==0 ); - u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo; - u.bt.r.nField = (u16)pOp->p3; - u.bt.r.flags = UNPACKED_PREFIX_MATCH; - u.bt.r.aMem = &aMem[pOp->p2]; + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p3; + r.default_rc = 0; + r.aMem = &aMem[pOp->p2]; #ifdef SQLITE_DEBUG - { int i; for(i=0; ideferredMoveto==0 ); - u.bt.pC->cacheStatus = CACHE_STALE; + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; break; } @@ -71253,28 +71749,27 @@ case OP_IdxDelete: { ** See also: Rowid, MakeRecord. */ case OP_IdxRowid: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bu */ BtCursor *pCrsr; VdbeCursor *pC; i64 rowid; -#endif /* local variables moved into u.bu */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bu.pC = p->apCsr[pOp->p1]; - assert( u.bu.pC!=0 ); - u.bu.pCrsr = u.bu.pC->pCursor; - assert( u.bu.pCrsr!=0 ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); pOut->flags = MEM_Null; - rc = sqlite3VdbeCursorMoveto(u.bu.pC); + rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc) ) goto abort_due_to_error; - assert( u.bu.pC->deferredMoveto==0 ); - assert( u.bu.pC->isTable==0 ); - if( !u.bu.pC->nullRow ){ - rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid); + assert( pC->deferredMoveto==0 ); + assert( pC->isTable==0 ); + if( !pC->nullRow ){ + rowid = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - pOut->u.i = u.bu.rowid; + pOut->u.i = rowid; pOut->flags = MEM_Int; } break; @@ -71284,65 +71779,87 @@ case OP_IdxRowid: { /* out2-prerelease */ ** Synopsis: key=r[P3@P4] ** ** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. ** ** If the P1 index entry is greater than or equal to the key value ** then jump to P2. Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxGT P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] ** -** If P5 is non-zero then the key value is increased by an epsilon -** prior to the comparison. This make the opcode work like IdxGT except -** that if the key from register P3 is a prefix of the key in the cursor, -** the result is false whereas it would be true with IdxGT. +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. +** +** If the P1 index entry is greater than the key value +** then jump to P2. Otherwise fall through to the next instruction. */ /* Opcode: IdxLT P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** ** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. ** ** If the P1 index entry is less than the key value then jump to P2. ** Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxLE P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. ** -** If P5 is non-zero then the key value is increased by an epsilon prior -** to the comparison. This makes the opcode work like IdxLE. +** If the P1 index entry is less than or equal to the key value then jump +** to P2. Otherwise fall through to the next instruction. */ +case OP_IdxLE: /* jump */ +case OP_IdxGT: /* jump */ case OP_IdxLT: /* jump */ -case OP_IdxGE: { /* jump */ -#if 0 /* local variables moved into u.bv */ +case OP_IdxGE: { /* jump */ VdbeCursor *pC; int res; UnpackedRecord r; -#endif /* local variables moved into u.bv */ assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bv.pC = p->apCsr[pOp->p1]; - assert( u.bv.pC!=0 ); - assert( u.bv.pC->isOrdered ); - assert( u.bv.pC->pCursor!=0); - assert( u.bv.pC->deferredMoveto==0 ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->isOrdered ); + assert( pC->pCursor!=0); + assert( pC->deferredMoveto==0 ); assert( pOp->p5==0 || pOp->p5==1 ); assert( pOp->p4type==P4_INT32 ); - u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo; - u.bv.r.nField = (u16)pOp->p4.i; - if( pOp->p5 ){ - u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH; + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp->p4.i; + if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); + r.default_rc = -1; }else{ - u.bv.r.flags = UNPACKED_PREFIX_MATCH; + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); + r.default_rc = 0; } - u.bv.r.aMem = &aMem[pOp->p3]; + r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG - { int i; for(i=0; iopcode==OP_IdxLT ){ - u.bv.res = -u.bv.res; + res = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res); + assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); + if( (pOp->opcode&1)==(OP_IdxLT&1) ){ + assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); + res = -res; }else{ - assert( pOp->opcode==OP_IdxGE ); - u.bv.res++; + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); + res++; } - if( u.bv.res>0 ){ + VdbeBranchTaken(res>0,2); + if( res>0 ){ pc = pOp->p2 - 1 ; } break; @@ -71369,43 +71886,42 @@ case OP_IdxGE: { /* jump */ ** See also: Clear */ case OP_Destroy: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bw */ int iMoved; int iCnt; Vdbe *pVdbe; int iDb; -#endif /* local variables moved into u.bw */ assert( p->readOnly==0 ); #ifndef SQLITE_OMIT_VIRTUALTABLE - u.bw.iCnt = 0; - for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){ - if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->bIsReader - && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 + iCnt = 0; + for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ + if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader + && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ - u.bw.iCnt++; + iCnt++; } } #else - u.bw.iCnt = db->nVdbeRead; + iCnt = db->nVdbeRead; #endif pOut->flags = MEM_Null; - if( u.bw.iCnt>1 ){ + if( iCnt>1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ - u.bw.iDb = pOp->p3; - assert( u.bw.iCnt==1 ); - assert( (p->btreeMask & (((yDbMask)1)<aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved); + iDb = pOp->p3; + assert( iCnt==1 ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; - pOut->u.i = u.bw.iMoved; + pOut->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM - if( rc==SQLITE_OK && u.bw.iMoved!=0 ){ - sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1); + if( rc==SQLITE_OK && iMoved!=0 ){ + sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1); /* All OP_Destroy operations occur on the same btree */ - assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 ); - resetSchemaOnFault = u.bw.iDb+1; + assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 ); + resetSchemaOnFault = iDb+1; } #endif } @@ -71431,23 +71947,20 @@ case OP_Destroy: { /* out2-prerelease */ ** See also: Destroy */ case OP_Clear: { -#if 0 /* local variables moved into u.bx */ int nChange; -#endif /* local variables moved into u.bx */ - - u.bx.nChange = 0; + + nChange = 0; assert( p->readOnly==0 ); - assert( pOp->p1!=1 ); assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); rc = sqlite3BtreeClearTable( - db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0) + db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); if( pOp->p3 ){ - p->nChange += u.bx.nChange; + p->nChange += nChange; if( pOp->p3>0 ){ assert( memIsValid(&aMem[pOp->p3]) ); memAboutToChange(p, &aMem[pOp->p3]); - aMem[pOp->p3].u.i += u.bx.nChange; + aMem[pOp->p3].u.i += nChange; } } break; @@ -71479,26 +71992,24 @@ case OP_Clear: { */ case OP_CreateIndex: /* out2-prerelease */ case OP_CreateTable: { /* out2-prerelease */ -#if 0 /* local variables moved into u.by */ int pgno; int flags; Db *pDb; -#endif /* local variables moved into u.by */ - u.by.pgno = 0; + pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); assert( p->readOnly==0 ); - u.by.pDb = &db->aDb[pOp->p1]; - assert( u.by.pDb->pBt!=0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ - /* u.by.flags = BTREE_INTKEY; */ - u.by.flags = BTREE_INTKEY; + /* flags = BTREE_INTKEY; */ + flags = BTREE_INTKEY; }else{ - u.by.flags = BTREE_BLOBKEY; + flags = BTREE_BLOBKEY; } - rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags); - pOut->u.i = u.by.pgno; + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); + pOut->u.i = pgno; break; } @@ -71511,44 +72022,42 @@ case OP_CreateTable: { /* out2-prerelease */ ** then runs the new virtual machine. It is thus a re-entrant opcode. */ case OP_ParseSchema: { -#if 0 /* local variables moved into u.bz */ int iDb; const char *zMaster; char *zSql; InitData initData; -#endif /* local variables moved into u.bz */ /* Any prepared statement that invokes this opcode will hold mutexes - ** on every btree. This is a prerequisite for invoking + ** on every btree. This is a prerequisite for invoking ** sqlite3InitCallback(). */ #ifdef SQLITE_DEBUG - for(u.bz.iDb=0; u.bz.iDbnDb; u.bz.iDb++){ - assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) ); + for(iDb=0; iDbnDb; iDb++){ + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); } #endif - u.bz.iDb = pOp->p1; - assert( u.bz.iDb>=0 && u.bz.iDbnDb ); - assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) ); + iDb = pOp->p1; + assert( iDb>=0 && iDbnDb ); + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); /* Used to be a conditional */ { - u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb); - u.bz.initData.db = db; - u.bz.initData.iDb = pOp->p1; - u.bz.initData.pzErrMsg = &p->zErrMsg; - u.bz.zSql = sqlite3MPrintf(db, + zMaster = SCHEMA_TABLE(iDb); + initData.db = db; + initData.iDb = pOp->p1; + initData.pzErrMsg = &p->zErrMsg; + zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", - db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z); - if( u.bz.zSql==0 ){ + db->aDb[iDb].zName, zMaster, pOp->p4.z); + if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ assert( db->init.busy==0 ); db->init.busy = 1; - u.bz.initData.rc = SQLITE_OK; + initData.rc = SQLITE_OK; assert( !db->mallocFailed ); - rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0); - if( rc==SQLITE_OK ) rc = u.bz.initData.rc; - sqlite3DbFree(db, u.bz.zSql); + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + if( rc==SQLITE_OK ) rc = initData.rc; + sqlite3DbFree(db, zSql); db->init.busy = 0; } } @@ -71556,7 +72065,7 @@ case OP_ParseSchema: { if( rc==SQLITE_NOMEM ){ goto no_mem; } - break; + break; } #if !defined(SQLITE_OMIT_ANALYZE) @@ -71632,42 +72141,40 @@ case OP_DropTrigger: { ** This opcode is used to implement the integrity_check pragma. */ case OP_IntegrityCk: { -#if 0 /* local variables moved into u.ca */ int nRoot; /* Number of tables to check. (Number of root pages.) */ int *aRoot; /* Array of rootpage numbers for tables to be checked */ int j; /* Loop counter */ int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ -#endif /* local variables moved into u.ca */ assert( p->bIsReader ); - u.ca.nRoot = pOp->p2; - assert( u.ca.nRoot>0 ); - u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) ); - if( u.ca.aRoot==0 ) goto no_mem; + nRoot = pOp->p2; + assert( nRoot>0 ); + aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); + if( aRoot==0 ) goto no_mem; assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - u.ca.pnErr = &aMem[pOp->p3]; - assert( (u.ca.pnErr->flags & MEM_Int)!=0 ); - assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 ); + pnErr = &aMem[pOp->p3]; + assert( (pnErr->flags & MEM_Int)!=0 ); + assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); pIn1 = &aMem[pOp->p1]; - for(u.ca.j=0; u.ca.jp5nDb ); assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 ); - u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot, - (int)u.ca.pnErr->u.i, &u.ca.nErr); - sqlite3DbFree(db, u.ca.aRoot); - u.ca.pnErr->u.i -= u.ca.nErr; + z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, + (int)pnErr->u.i, &nErr); + sqlite3DbFree(db, aRoot); + pnErr->u.i -= nErr; sqlite3VdbeMemSetNull(pIn1); - if( u.ca.nErr==0 ){ - assert( u.ca.z==0 ); - }else if( u.ca.z==0 ){ + if( nErr==0 ){ + assert( z==0 ); + }else if( z==0 ){ goto no_mem; }else{ - sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free); + sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); } UPDATE_MAX_BLOBSIZE(pIn1); sqlite3VdbeChangeEncoding(pIn1, encoding); @@ -71703,20 +72210,20 @@ case OP_RowSetAdd: { /* in1, in2 */ ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, in1, out3 */ -#if 0 /* local variables moved into u.cb */ i64 val; -#endif /* local variables moved into u.cb */ pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_RowSet)==0 - || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0 + if( (pIn1->flags & MEM_RowSet)==0 + || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); pc = pOp->p2 - 1; + VdbeBranchTaken(1,2); }else{ /* A value was pulled from the index */ - sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val); + sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); + VdbeBranchTaken(0,2); } goto check_for_interrupt; } @@ -71746,14 +72253,12 @@ case OP_RowSetRead: { /* jump, in1, out3 */ ** inserted as part of some other set). */ case OP_RowSetTest: { /* jump, in1, in3 */ -#if 0 /* local variables moved into u.cc */ int iSet; int exists; -#endif /* local variables moved into u.cc */ pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; - u.cc.iSet = pOp->p4.i; + iSet = pOp->p4.i; assert( pIn3->flags&MEM_Int ); /* If there is anything other than a rowset object in memory cell P1, @@ -71765,17 +72270,18 @@ case OP_RowSetTest: { /* jump, in1, in3 */ } assert( pOp->p4type==P4_INT32 ); - assert( u.cc.iSet==-1 || u.cc.iSet>=0 ); - if( u.cc.iSet ){ - u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet, - (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff), + assert( iSet==-1 || iSet>=0 ); + if( iSet ){ + exists = sqlite3RowSetTest(pIn1->u.pRowSet, + (u8)(iSet>=0 ? iSet & 0xf : 0xff), pIn3->u.i); - if( u.cc.exists ){ + VdbeBranchTaken(exists!=0,2); + if( exists ){ pc = pOp->p2 - 1; break; } } - if( u.cc.iSet>=0 ){ + if( iSet>=0 ){ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); } break; @@ -71784,7 +72290,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ #ifndef SQLITE_OMIT_TRIGGER -/* Opcode: Program P1 P2 P3 P4 * +/* Opcode: Program P1 P2 P3 P4 P5 ** ** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). ** @@ -71796,9 +72302,10 @@ case OP_RowSetTest: { /* jump, in1, in3 */ ** memory required by the sub-vdbe at runtime. ** ** P4 is a pointer to the VM containing the trigger program. +** +** If P5 is non-zero, then recursive program invocation is enabled. */ case OP_Program: { /* jump */ -#if 0 /* local variables moved into u.cd */ int nMem; /* Number of memory registers for sub-program */ int nByte; /* Bytes of runtime space required for sub-program */ Mem *pRt; /* Register to allocate runtime space */ @@ -71807,27 +72314,26 @@ case OP_Program: { /* jump */ VdbeFrame *pFrame; /* New vdbe frame to execute in */ SubProgram *pProgram; /* Sub-program to execute */ void *t; /* Token identifying trigger */ -#endif /* local variables moved into u.cd */ - - u.cd.pProgram = pOp->p4.pProgram; - u.cd.pRt = &aMem[pOp->p3]; - assert( u.cd.pProgram->nOp>0 ); - /* If the p5 flag is clear, then recursive invocation of triggers is + pProgram = pOp->p4.pProgram; + pRt = &aMem[pOp->p3]; + assert( pProgram->nOp>0 ); + + /* If the p5 flag is clear, then recursive invocation of triggers is ** disabled for backwards compatibility (p5 is set if this sub-program ** is really a trigger, not a foreign key action, and the flag set ** and cleared by the "PRAGMA recursive_triggers" command is clear). - ** - ** It is recursive invocation of triggers, at the SQL level, that is - ** disabled. In some cases a single trigger may generate more than one - ** SubProgram (if the trigger may be executed with more than one different + ** + ** It is recursive invocation of triggers, at the SQL level, that is + ** disabled. In some cases a single trigger may generate more than one + ** SubProgram (if the trigger may be executed with more than one different ** ON CONFLICT algorithm). SubProgram structures associated with a - ** single trigger all have the same value for the SubProgram.token + ** single trigger all have the same value for the SubProgram.token ** variable. */ if( pOp->p5 ){ - u.cd.t = u.cd.pProgram->token; - for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent); - if( u.cd.pFrame ) break; + t = pProgram->token; + for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent); + if( pFrame ) break; } if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ @@ -71836,69 +72342,69 @@ case OP_Program: { /* jump */ break; } - /* Register u.cd.pRt is used to store the memory required to save the state + /* Register pRt is used to store the memory required to save the state ** of the current program, and the memory required at runtime to execute - ** the trigger program. If this trigger has been fired before, then u.cd.pRt + ** the trigger program. If this trigger has been fired before, then pRt ** is already allocated. Otherwise, it must be initialized. */ - if( (u.cd.pRt->flags&MEM_Frame)==0 ){ - /* SubProgram.nMem is set to the number of memory cells used by the + if( (pRt->flags&MEM_Frame)==0 ){ + /* SubProgram.nMem is set to the number of memory cells used by the ** program stored in SubProgram.aOp. As well as these, one memory ** cell is required for each cursor used by the program. Set local - ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value. + ** variable nMem (and later, VdbeFrame.nChildMem) to this value. */ - u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr; - u.cd.nByte = ROUND8(sizeof(VdbeFrame)) - + u.cd.nMem * sizeof(Mem) - + u.cd.pProgram->nCsr * sizeof(VdbeCursor *) - + u.cd.pProgram->nOnce * sizeof(u8); - u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte); - if( !u.cd.pFrame ){ + nMem = pProgram->nMem + pProgram->nCsr; + nByte = ROUND8(sizeof(VdbeFrame)) + + nMem * sizeof(Mem) + + pProgram->nCsr * sizeof(VdbeCursor *) + + pProgram->nOnce * sizeof(u8); + pFrame = sqlite3DbMallocZero(db, nByte); + if( !pFrame ){ goto no_mem; } - sqlite3VdbeMemRelease(u.cd.pRt); - u.cd.pRt->flags = MEM_Frame; - u.cd.pRt->u.pFrame = u.cd.pFrame; + sqlite3VdbeMemRelease(pRt); + pRt->flags = MEM_Frame; + pRt->u.pFrame = pFrame; - u.cd.pFrame->v = p; - u.cd.pFrame->nChildMem = u.cd.nMem; - u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr; - u.cd.pFrame->pc = pc; - u.cd.pFrame->aMem = p->aMem; - u.cd.pFrame->nMem = p->nMem; - u.cd.pFrame->apCsr = p->apCsr; - u.cd.pFrame->nCursor = p->nCursor; - u.cd.pFrame->aOp = p->aOp; - u.cd.pFrame->nOp = p->nOp; - u.cd.pFrame->token = u.cd.pProgram->token; - u.cd.pFrame->aOnceFlag = p->aOnceFlag; - u.cd.pFrame->nOnceFlag = p->nOnceFlag; + pFrame->v = p; + pFrame->nChildMem = nMem; + pFrame->nChildCsr = pProgram->nCsr; + pFrame->pc = pc; + pFrame->aMem = p->aMem; + pFrame->nMem = p->nMem; + pFrame->apCsr = p->apCsr; + pFrame->nCursor = p->nCursor; + pFrame->aOp = p->aOp; + pFrame->nOp = p->nOp; + pFrame->token = pProgram->token; + pFrame->aOnceFlag = p->aOnceFlag; + pFrame->nOnceFlag = p->nOnceFlag; - u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem]; - for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){ - u.cd.pMem->flags = MEM_Invalid; - u.cd.pMem->db = db; + pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; + for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ + pMem->flags = MEM_Undefined; + pMem->db = db; } }else{ - u.cd.pFrame = u.cd.pRt->u.pFrame; - assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem ); - assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr ); - assert( pc==u.cd.pFrame->pc ); + pFrame = pRt->u.pFrame; + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); + assert( pProgram->nCsr==pFrame->nChildCsr ); + assert( pc==pFrame->pc ); } p->nFrame++; - u.cd.pFrame->pParent = p->pFrame; - u.cd.pFrame->lastRowid = lastRowid; - u.cd.pFrame->nChange = p->nChange; + pFrame->pParent = p->pFrame; + pFrame->lastRowid = lastRowid; + pFrame->nChange = p->nChange; p->nChange = 0; - p->pFrame = u.cd.pFrame; - p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1]; - p->nMem = u.cd.pFrame->nChildMem; - p->nCursor = (u16)u.cd.pFrame->nChildCsr; + p->pFrame = pFrame; + p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; + p->nMem = pFrame->nChildMem; + p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; - p->aOp = aOp = u.cd.pProgram->aOp; - p->nOp = u.cd.pProgram->nOp; + p->aOp = aOp = pProgram->aOp; + p->nOp = pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; - p->nOnceFlag = u.cd.pProgram->nOnce; + p->nOnceFlag = pProgram->nOnce; pc = -1; memset(p->aOnceFlag, 0, p->nOnceFlag); @@ -71918,13 +72424,11 @@ case OP_Program: { /* jump */ ** calling OP_Program instruction. */ case OP_Param: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ce */ VdbeFrame *pFrame; Mem *pIn; -#endif /* local variables moved into u.ce */ - u.ce.pFrame = p->pFrame; - u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1]; - sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem); + pFrame = p->pFrame; + pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; + sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); break; } @@ -71964,8 +72468,10 @@ case OP_FkCounter: { */ case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ + VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; }else{ + VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; } break; @@ -71985,22 +72491,19 @@ case OP_FkIfZero: { /* jump */ ** an integer. */ case OP_MemMax: { /* in2 */ -#if 0 /* local variables moved into u.cf */ - Mem *pIn1; VdbeFrame *pFrame; -#endif /* local variables moved into u.cf */ if( p->pFrame ){ - for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent); - u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1]; + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); + pIn1 = &pFrame->aMem[pOp->p1]; }else{ - u.cf.pIn1 = &aMem[pOp->p1]; + pIn1 = &aMem[pOp->p1]; } - assert( memIsValid(u.cf.pIn1) ); - sqlite3VdbeMemIntegerify(u.cf.pIn1); + assert( memIsValid(pIn1) ); + sqlite3VdbeMemIntegerify(pIn1); pIn2 = &aMem[pOp->p2]; sqlite3VdbeMemIntegerify(pIn2); - if( u.cf.pIn1->u.iu.i){ - u.cf.pIn1->u.i = pIn2->u.i; + if( pIn1->u.iu.i){ + pIn1->u.i = pIn2->u.i; } break; } @@ -72017,6 +72520,7 @@ case OP_MemMax: { /* in2 */ case OP_IfPos: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken( pIn1->u.i>0, 2); if( pIn1->u.i>0 ){ pc = pOp->p2 - 1; } @@ -72034,6 +72538,7 @@ case OP_IfPos: { /* jump, in1 */ case OP_IfNeg: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i<0, 2); if( pIn1->u.i<0 ){ pc = pOp->p2 - 1; } @@ -72053,6 +72558,7 @@ case OP_IfZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); pIn1->u.i += pOp->p3; + VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ){ pc = pOp->p2 - 1; } @@ -72071,56 +72577,53 @@ case OP_IfZero: { /* jump, in1 */ ** successors. */ case OP_AggStep: { -#if 0 /* local variables moved into u.cg */ int n; int i; Mem *pMem; Mem *pRec; sqlite3_context ctx; sqlite3_value **apVal; -#endif /* local variables moved into u.cg */ - - u.cg.n = pOp->p5; - assert( u.cg.n>=0 ); - u.cg.pRec = &aMem[pOp->p2]; - u.cg.apVal = p->apArg; - assert( u.cg.apVal || u.cg.n==0 ); - for(u.cg.i=0; u.cg.ip4.pFunc; + + n = pOp->p5; + assert( n>=0 ); + pRec = &aMem[pOp->p2]; + apVal = p->apArg; + assert( apVal || n==0 ); + for(i=0; ip4.pFunc; assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3]; - u.cg.pMem->n++; - u.cg.ctx.s.flags = MEM_Null; - u.cg.ctx.s.z = 0; - u.cg.ctx.s.zMalloc = 0; - u.cg.ctx.s.xDel = 0; - u.cg.ctx.s.db = db; - u.cg.ctx.isError = 0; - u.cg.ctx.pColl = 0; - u.cg.ctx.skipFlag = 0; - if( u.cg.ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + ctx.pMem = pMem = &aMem[pOp->p3]; + pMem->n++; + ctx.s.flags = MEM_Null; + ctx.s.z = 0; + ctx.s.zMalloc = 0; + ctx.s.xDel = 0; + ctx.s.db = db; + ctx.isError = 0; + ctx.pColl = 0; + ctx.skipFlag = 0; + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); - u.cg.ctx.pColl = pOp[-1].p4.pColl; + ctx.pColl = pOp[-1].p4.pColl; } - (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */ - if( u.cg.ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s)); - rc = u.cg.ctx.isError; + (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; } - if( u.cg.ctx.skipFlag ){ + if( ctx.skipFlag ){ assert( pOp[-1].opcode==OP_CollSeq ); - u.cg.i = pOp[-1].p1; - if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1); + i = pOp[-1].p1; + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); } - sqlite3VdbeMemRelease(&u.cg.ctx.s); + sqlite3VdbeMemRelease(&ctx.s); break; } @@ -72139,19 +72642,17 @@ case OP_AggStep: { ** the step function was not previously called. */ case OP_AggFinal: { -#if 0 /* local variables moved into u.ch */ Mem *pMem; -#endif /* local variables moved into u.ch */ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); - u.ch.pMem = &aMem[pOp->p1]; - assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); - rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc); + pMem = &aMem[pOp->p1]; + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); + rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); if( rc ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem)); } - sqlite3VdbeChangeEncoding(u.ch.pMem, encoding); - UPDATE_MAX_BLOBSIZE(u.ch.pMem); - if( sqlite3VdbeMemTooBig(u.ch.pMem) ){ + sqlite3VdbeChangeEncoding(pMem, encoding); + UPDATE_MAX_BLOBSIZE(pMem); + if( sqlite3VdbeMemTooBig(pMem) ){ goto too_big; } break; @@ -72170,33 +72671,31 @@ case OP_AggFinal: { ** mem[P3+2] are initialized to -1. */ case OP_Checkpoint: { -#if 0 /* local variables moved into u.ci */ int i; /* Loop counter */ int aRes[3]; /* Results */ Mem *pMem; /* Write results here */ -#endif /* local variables moved into u.ci */ assert( p->readOnly==0 ); - u.ci.aRes[0] = 0; - u.ci.aRes[1] = u.ci.aRes[2] = -1; + aRes[0] = 0; + aRes[1] = aRes[2] = -1; assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE || pOp->p2==SQLITE_CHECKPOINT_FULL || pOp->p2==SQLITE_CHECKPOINT_RESTART ); - rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]); + rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); if( rc==SQLITE_BUSY ){ rc = SQLITE_OK; - u.ci.aRes[0] = 1; - } - for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){ - sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]); + aRes[0] = 1; } + for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){ + sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]); + } break; }; #endif #ifndef SQLITE_OMIT_PRAGMA -/* Opcode: JournalMode P1 P2 P3 * P5 +/* Opcode: JournalMode P1 P2 P3 * * ** ** Change the journal mode of database P1 to P3. P3 must be one of the ** PAGER_JOURNALMODE_XXX values. If changing between the various rollback @@ -72208,7 +72707,6 @@ case OP_Checkpoint: { ** Write a string containing the final journal-mode to register P2. */ case OP_JournalMode: { /* out2-prerelease */ -#if 0 /* local variables moved into u.cj */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ @@ -72216,86 +72714,85 @@ case OP_JournalMode: { /* out2-prerelease */ #ifndef SQLITE_OMIT_WAL const char *zFilename; /* Name of database file for pPager */ #endif -#endif /* local variables moved into u.cj */ - u.cj.eNew = pOp->p3; - assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE - || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE - || u.cj.eNew==PAGER_JOURNALMODE_PERSIST - || u.cj.eNew==PAGER_JOURNALMODE_OFF - || u.cj.eNew==PAGER_JOURNALMODE_MEMORY - || u.cj.eNew==PAGER_JOURNALMODE_WAL - || u.cj.eNew==PAGER_JOURNALMODE_QUERY + eNew = pOp->p3; + assert( eNew==PAGER_JOURNALMODE_DELETE + || eNew==PAGER_JOURNALMODE_TRUNCATE + || eNew==PAGER_JOURNALMODE_PERSIST + || eNew==PAGER_JOURNALMODE_OFF + || eNew==PAGER_JOURNALMODE_MEMORY + || eNew==PAGER_JOURNALMODE_WAL + || eNew==PAGER_JOURNALMODE_QUERY ); assert( pOp->p1>=0 && pOp->p1nDb ); assert( p->readOnly==0 ); - u.cj.pBt = db->aDb[pOp->p1].pBt; - u.cj.pPager = sqlite3BtreePager(u.cj.pBt); - u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager); - if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld; - if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld; + pBt = db->aDb[pOp->p1].pBt; + pPager = sqlite3BtreePager(pBt); + eOld = sqlite3PagerGetJournalMode(pPager); + if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; + if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; #ifndef SQLITE_OMIT_WAL - u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1); + zFilename = sqlite3PagerFilename(pPager, 1); /* Do not allow a transition to journal_mode=WAL for a database - ** in temporary storage or if the VFS does not support shared memory + ** in temporary storage or if the VFS does not support shared memory */ - if( u.cj.eNew==PAGER_JOURNALMODE_WAL - && (sqlite3Strlen30(u.cj.zFilename)==0 /* Temp file */ - || !sqlite3PagerWalSupported(u.cj.pPager)) /* No shared-memory support */ + if( eNew==PAGER_JOURNALMODE_WAL + && (sqlite3Strlen30(zFilename)==0 /* Temp file */ + || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */ ){ - u.cj.eNew = u.cj.eOld; + eNew = eOld; } - if( (u.cj.eNew!=u.cj.eOld) - && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL) + if( (eNew!=eOld) + && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL) ){ if( !db->autoCommit || db->nVdbeRead>1 ){ rc = SQLITE_ERROR; - sqlite3SetString(&p->zErrMsg, db, + sqlite3SetString(&p->zErrMsg, db, "cannot change %s wal mode from within a transaction", - (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") + (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") ); break; }else{ - - if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){ + + if( eOld==PAGER_JOURNALMODE_WAL ){ /* If leaving WAL mode, close the log file. If successful, the call - ** to PagerCloseWal() checkpoints and deletes the write-ahead-log - ** file. An EXCLUSIVE lock may still be held on the database file - ** after a successful return. + ** to PagerCloseWal() checkpoints and deletes the write-ahead-log + ** file. An EXCLUSIVE lock may still be held on the database file + ** after a successful return. */ - rc = sqlite3PagerCloseWal(u.cj.pPager); + rc = sqlite3PagerCloseWal(pPager); if( rc==SQLITE_OK ){ - sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew); + sqlite3PagerSetJournalMode(pPager, eNew); } - }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){ + }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ /* Cannot transition directly from MEMORY to WAL. Use mode OFF ** as an intermediate */ - sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF); + sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF); } - + /* Open a transaction on the database file. Regardless of the journal ** mode, this transaction always uses a rollback journal. */ - assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 ); + assert( sqlite3BtreeIsInTrans(pBt)==0 ); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); + rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); } } } #endif /* ifndef SQLITE_OMIT_WAL */ if( rc ){ - u.cj.eNew = u.cj.eOld; + eNew = eOld; } - u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew); + eNew = sqlite3PagerSetJournalMode(pPager, eNew); pOut = &aMem[pOp->p2]; pOut->flags = MEM_Str|MEM_Static|MEM_Term; - pOut->z = (char *)sqlite3JournalModename(u.cj.eNew); + pOut->z = (char *)sqlite3JournalModename(eNew); pOut->n = sqlite3Strlen30(pOut->z); pOut->enc = SQLITE_UTF8; sqlite3VdbeChangeEncoding(pOut, encoding); @@ -72325,15 +72822,14 @@ case OP_Vacuum: { ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* jump */ -#if 0 /* local variables moved into u.ck */ Btree *pBt; -#endif /* local variables moved into u.ck */ assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); assert( p->readOnly==0 ); - u.ck.pBt = db->aDb[pOp->p1].pBt; - rc = sqlite3BtreeIncrVacuum(u.ck.pBt); + pBt = db->aDb[pOp->p1].pBt; + rc = sqlite3BtreeIncrVacuum(pBt); + VdbeBranchTaken(rc==SQLITE_DONE,2); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; @@ -72404,12 +72900,10 @@ case OP_TableLock: { ** code will be set to SQLITE_LOCKED. */ case OP_VBegin: { -#if 0 /* local variables moved into u.cl */ VTable *pVTab; -#endif /* local variables moved into u.cl */ - u.cl.pVTab = pOp->p4.pVtab; - rc = sqlite3VtabBegin(db, u.cl.pVTab); - if( u.cl.pVTab ) sqlite3VtabImportErrmsg(p, u.cl.pVTab->pVtab); + pVTab = pOp->p4.pVtab; + rc = sqlite3VtabBegin(db, pVTab); + if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -72448,32 +72942,30 @@ case OP_VDestroy: { ** table and stores that cursor in P1. */ case OP_VOpen: { -#if 0 /* local variables moved into u.cm */ VdbeCursor *pCur; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; sqlite3_module *pModule; -#endif /* local variables moved into u.cm */ assert( p->bIsReader ); - u.cm.pCur = 0; - u.cm.pVtabCursor = 0; - u.cm.pVtab = pOp->p4.pVtab->pVtab; - u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule; - assert(u.cm.pVtab && u.cm.pModule); - rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor); - sqlite3VtabImportErrmsg(p, u.cm.pVtab); + pCur = 0; + pVtabCursor = 0; + pVtab = pOp->p4.pVtab->pVtab; + pModule = (sqlite3_module *)pVtab->pModule; + assert(pVtab && pModule); + rc = pModule->xOpen(pVtab, &pVtabCursor); + sqlite3VtabImportErrmsg(p, pVtab); if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ - u.cm.pVtabCursor->pVtab = u.cm.pVtab; + pVtabCursor->pVtab = pVtab; /* Initialize vdbe cursor object */ - u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0); - if( u.cm.pCur ){ - u.cm.pCur->pVtabCursor = u.cm.pVtabCursor; + pCur = allocateCursor(p, pOp->p1, 0, -1, 0); + if( pCur ){ + pCur->pVtabCursor = pVtabCursor; }else{ db->mallocFailed = 1; - u.cm.pModule->xClose(u.cm.pVtabCursor); + pModule->xClose(pVtabCursor); } } break; @@ -72501,7 +72993,6 @@ case OP_VOpen: { ** A jump is made to P2 if the result set after filtering would be empty. */ case OP_VFilter: { /* jump */ -#if 0 /* local variables moved into u.cn */ int nArg; int iQuery; const sqlite3_module *pModule; @@ -72513,45 +73004,43 @@ case OP_VFilter: { /* jump */ int res; int i; Mem **apArg; -#endif /* local variables moved into u.cn */ - - u.cn.pQuery = &aMem[pOp->p3]; - u.cn.pArgc = &u.cn.pQuery[1]; - u.cn.pCur = p->apCsr[pOp->p1]; - assert( memIsValid(u.cn.pQuery) ); - REGISTER_TRACE(pOp->p3, u.cn.pQuery); - assert( u.cn.pCur->pVtabCursor ); - u.cn.pVtabCursor = u.cn.pCur->pVtabCursor; - u.cn.pVtab = u.cn.pVtabCursor->pVtab; - u.cn.pModule = u.cn.pVtab->pModule; + + pQuery = &aMem[pOp->p3]; + pArgc = &pQuery[1]; + pCur = p->apCsr[pOp->p1]; + assert( memIsValid(pQuery) ); + REGISTER_TRACE(pOp->p3, pQuery); + assert( pCur->pVtabCursor ); + pVtabCursor = pCur->pVtabCursor; + pVtab = pVtabCursor->pVtab; + pModule = pVtab->pModule; /* Grab the index number and argc parameters */ - assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int ); - u.cn.nArg = (int)u.cn.pArgc->u.i; - u.cn.iQuery = (int)u.cn.pQuery->u.i; + assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); + nArg = (int)pArgc->u.i; + iQuery = (int)pQuery->u.i; /* Invoke the xFilter method */ { - u.cn.res = 0; - u.cn.apArg = p->apArg; - for(u.cn.i = 0; u.cn.iapArg; + for(i = 0; iinVtabMethod = 1; - rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg); + rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); p->inVtabMethod = 0; - sqlite3VtabImportErrmsg(p, u.cn.pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ - u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor); + res = pModule->xEof(pVtabCursor); } - - if( u.cn.res ){ + VdbeBranchTaken(res!=0,2); + if( res ){ pc = pOp->p2 - 1; } } - u.cn.pCur->nullRow = 0; + pCur->nullRow = 0; break; } @@ -72566,51 +73055,49 @@ case OP_VFilter: { /* jump */ ** P1 cursor is pointing to into register P3. */ case OP_VColumn: { -#if 0 /* local variables moved into u.co */ sqlite3_vtab *pVtab; const sqlite3_module *pModule; Mem *pDest; sqlite3_context sContext; -#endif /* local variables moved into u.co */ VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - u.co.pDest = &aMem[pOp->p3]; - memAboutToChange(p, u.co.pDest); + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); if( pCur->nullRow ){ - sqlite3VdbeMemSetNull(u.co.pDest); + sqlite3VdbeMemSetNull(pDest); break; } - u.co.pVtab = pCur->pVtabCursor->pVtab; - u.co.pModule = u.co.pVtab->pModule; - assert( u.co.pModule->xColumn ); - memset(&u.co.sContext, 0, sizeof(u.co.sContext)); + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xColumn ); + memset(&sContext, 0, sizeof(sContext)); /* The output cell may already have a buffer allocated. Move - ** the current contents to u.co.sContext.s so in case the user-function - ** can use the already allocated buffer instead of allocating a + ** the current contents to sContext.s so in case the user-function + ** can use the already allocated buffer instead of allocating a ** new one. */ - sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest); - MemSetTypeFlag(&u.co.sContext.s, MEM_Null); + sqlite3VdbeMemMove(&sContext.s, pDest); + MemSetTypeFlag(&sContext.s, MEM_Null); - rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2); - sqlite3VtabImportErrmsg(p, u.co.pVtab); - if( u.co.sContext.isError ){ - rc = u.co.sContext.isError; + rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); + sqlite3VtabImportErrmsg(p, pVtab); + if( sContext.isError ){ + rc = sContext.isError; } /* Copy the result of the function to the P3 register. We ** do this regardless of whether or not an error occurred to ensure any - ** dynamic allocation in u.co.sContext.s (a Mem struct) is released. + ** dynamic allocation in sContext.s (a Mem struct) is released. */ - sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding); - sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s); - REGISTER_TRACE(pOp->p3, u.co.pDest); - UPDATE_MAX_BLOBSIZE(u.co.pDest); + sqlite3VdbeChangeEncoding(&sContext.s, encoding); + sqlite3VdbeMemMove(pDest, &sContext.s); + REGISTER_TRACE(pOp->p3, pDest); + UPDATE_MAX_BLOBSIZE(pDest); - if( sqlite3VdbeMemTooBig(u.co.pDest) ){ + if( sqlite3VdbeMemTooBig(pDest) ){ goto too_big; } break; @@ -72625,38 +73112,36 @@ case OP_VColumn: { ** the end of its result set, then fall through to the next instruction. */ case OP_VNext: { /* jump */ -#if 0 /* local variables moved into u.cp */ sqlite3_vtab *pVtab; const sqlite3_module *pModule; int res; VdbeCursor *pCur; -#endif /* local variables moved into u.cp */ - u.cp.res = 0; - u.cp.pCur = p->apCsr[pOp->p1]; - assert( u.cp.pCur->pVtabCursor ); - if( u.cp.pCur->nullRow ){ + res = 0; + pCur = p->apCsr[pOp->p1]; + assert( pCur->pVtabCursor ); + if( pCur->nullRow ){ break; } - u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab; - u.cp.pModule = u.cp.pVtab->pModule; - assert( u.cp.pModule->xNext ); + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xNext ); /* Invoke the xNext() method of the module. There is no way for the ** underlying implementation to return an error if one occurs during - ** xNext(). Instead, if an error occurs, true is returned (indicating that + ** xNext(). Instead, if an error occurs, true is returned (indicating that ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ p->inVtabMethod = 1; - rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor); + rc = pModule->xNext(pCur->pVtabCursor); p->inVtabMethod = 0; - sqlite3VtabImportErrmsg(p, u.cp.pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ - u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor); + res = pModule->xEof(pCur->pVtabCursor); } - - if( !u.cp.res ){ + VdbeBranchTaken(!res,2); + if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } @@ -72672,25 +73157,23 @@ case OP_VNext: { /* jump */ ** in register P1 is passed as the zName argument to the xRename method. */ case OP_VRename: { -#if 0 /* local variables moved into u.cq */ sqlite3_vtab *pVtab; Mem *pName; -#endif /* local variables moved into u.cq */ - u.cq.pVtab = pOp->p4.pVtab->pVtab; - u.cq.pName = &aMem[pOp->p1]; - assert( u.cq.pVtab->pModule->xRename ); - assert( memIsValid(u.cq.pName) ); + pVtab = pOp->p4.pVtab->pVtab; + pName = &aMem[pOp->p1]; + assert( pVtab->pModule->xRename ); + assert( memIsValid(pName) ); assert( p->readOnly==0 ); - REGISTER_TRACE(pOp->p1, u.cq.pName); - assert( u.cq.pName->flags & MEM_Str ); - testcase( u.cq.pName->enc==SQLITE_UTF8 ); - testcase( u.cq.pName->enc==SQLITE_UTF16BE ); - testcase( u.cq.pName->enc==SQLITE_UTF16LE ); - rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8); + REGISTER_TRACE(pOp->p1, pName); + assert( pName->flags & MEM_Str ); + testcase( pName->enc==SQLITE_UTF8 ); + testcase( pName->enc==SQLITE_UTF16BE ); + testcase( pName->enc==SQLITE_UTF16LE ); + rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); if( rc==SQLITE_OK ){ - rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z); - sqlite3VtabImportErrmsg(p, u.cq.pVtab); + rc = pVtab->pModule->xRename(pVtab, pName->z); + sqlite3VtabImportErrmsg(p, pVtab); p->expired = 0; } break; @@ -72698,7 +73181,7 @@ case OP_VRename: { #endif #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VUpdate P1 P2 P3 P4 * +/* Opcode: VUpdate P1 P2 P3 P4 P5 ** Synopsis: data=r[P3@P2] ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. @@ -72721,9 +73204,11 @@ case OP_VRename: { ** P1 is a boolean flag. If it is set to true and the xUpdate call ** is successful, then the value returned by sqlite3_last_insert_rowid() ** is set to the value of the rowid for the row just inserted. +** +** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to +** apply in the case of a constraint failure on an insert or update. */ case OP_VUpdate: { -#if 0 /* local variables moved into u.cr */ sqlite3_vtab *pVtab; sqlite3_module *pModule; int nArg; @@ -72731,34 +73216,32 @@ case OP_VUpdate: { sqlite_int64 rowid; Mem **apArg; Mem *pX; -#endif /* local variables moved into u.cr */ - assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback + assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); assert( p->readOnly==0 ); - u.cr.pVtab = pOp->p4.pVtab->pVtab; - u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule; - u.cr.nArg = pOp->p2; + pVtab = pOp->p4.pVtab->pVtab; + pModule = (sqlite3_module *)pVtab->pModule; + nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); - if( ALWAYS(u.cr.pModule->xUpdate) ){ + if( ALWAYS(pModule->xUpdate) ){ u8 vtabOnConflict = db->vtabOnConflict; - u.cr.apArg = p->apArg; - u.cr.pX = &aMem[pOp->p3]; - for(u.cr.i=0; u.cr.iapArg; + pX = &aMem[pOp->p3]; + for(i=0; ivtabOnConflict = pOp->p5; - rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid); + rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); db->vtabOnConflict = vtabOnConflict; - sqlite3VtabImportErrmsg(p, u.cr.pVtab); + sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK && pOp->p1 ){ - assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) ); - db->lastRowid = lastRowid = u.cr.rowid; + assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); + db->lastRowid = lastRowid = rowid; } if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ if( pOp->p5==OE_Ignore ){ @@ -72811,46 +73294,54 @@ case OP_MaxPgcnt: { /* out2-prerelease */ #endif -#ifndef SQLITE_OMIT_TRACE -/* Opcode: Trace * * * P4 * +/* Opcode: Init * P2 * P4 * +** Synopsis: Start at P2 +** +** Programs contain a single instance of this opcode as the very first +** opcode. ** ** If tracing is enabled (by the sqlite3_trace()) interface, then ** the UTF-8 string contained in P4 is emitted on the trace callback. +** Or if P4 is blank, use the string returned by sqlite3_sql(). +** +** If P2 is not zero, jump to instruction P2. */ -case OP_Trace: { -#if 0 /* local variables moved into u.cs */ +case OP_Init: { /* jump */ char *zTrace; char *z; -#endif /* local variables moved into u.cs */ + if( pOp->p2 ){ + pc = pOp->p2 - 1; + } +#ifndef SQLITE_OMIT_TRACE if( db->xTrace && !p->doingRerun - && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 + && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){ - u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace); - db->xTrace(db->pTraceArg, u.cs.z); - sqlite3DbFree(db, u.cs.z); + z = sqlite3VdbeExpandSql(p, zTrace); + db->xTrace(db->pTraceArg, z); + sqlite3DbFree(db, z); } #ifdef SQLITE_USE_FCNTL_TRACE - u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); - if( u.cs.zTrace ){ + zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); + if( zTrace ){ int i; for(i=0; inDb; i++){ - if( ((1<btreeMask)==0 ) continue; - sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, u.cs.zTrace); + if( MASKBIT(i) & p->btreeMask)==0 ) continue; + sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); } } #endif /* SQLITE_USE_FCNTL_TRACE */ #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 - && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 + && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){ - sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace); + sqlite3DebugPrintf("SQL-trace: %s\n", zTrace); } #endif /* SQLITE_DEBUG */ +#endif /* SQLITE_OMIT_TRACE */ break; } -#endif /* Opcode: Noop * * * * * @@ -72882,10 +73373,6 @@ default: { /* This is really OP_Noop and OP_Explain */ u64 elapsed = sqlite3Hwtime() - start; pOp->cycles += elapsed; pOp->cnt++; -#if 0 - fprintf(stdout, "%10llu ", elapsed); - sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]); -#endif } #endif @@ -72975,6 +73462,7 @@ abort_due_to_interrupt: goto vdbe_error_halt; } + /************** End of vdbe.c ************************************************/ /************** Begin file vdbeblob.c ****************************************/ /* @@ -73110,22 +73598,20 @@ SQLITE_API int sqlite3_blob_open( ** which closes the b-tree cursor and (possibly) commits the ** transaction. */ + static const int iLn = VDBE_OFFSET_LINENO(4); static const VdbeOpList openBlob[] = { - {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */ - {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */ - {OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */ - + /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */ + {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */ /* One of the following two instructions is replaced by an OP_Noop. */ - {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ - {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */ - - {OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */ - {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */ - {OP_Column, 0, 0, 1}, /* 7 */ - {OP_ResultRow, 1, 0, 0}, /* 8 */ - {OP_Goto, 0, 5, 0}, /* 9 */ - {OP_Close, 0, 0, 0}, /* 10 */ - {OP_Halt, 0, 0, 0}, /* 11 */ + {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ + {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ + {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */ + {OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 6 */ + {OP_ResultRow, 1, 0, 0}, /* 7 */ + {OP_Goto, 0, 4, 0}, /* 8 */ + {OP_Close, 0, 0, 0}, /* 9 */ + {OP_Halt, 0, 0, 0}, /* 10 */ }; int rc = SQLITE_OK; @@ -73232,42 +73718,37 @@ SQLITE_API int sqlite3_blob_open( } } - pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db); + pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse); assert( pBlob->pStmt || db->mallocFailed ); if( pBlob->pStmt ){ Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); - - /* Configure the OP_Transaction */ - sqlite3VdbeChangeP1(v, 0, iDb); - sqlite3VdbeChangeP2(v, 0, flags); - - /* Configure the OP_VerifyCookie */ - sqlite3VdbeChangeP1(v, 1, iDb); - sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); - sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration); + sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, + pTab->pSchema->schema_cookie, + pTab->pSchema->iGeneration); + sqlite3VdbeChangeP5(v, 1); + sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); /* Configure the OP_TableLock instruction */ #ifdef SQLITE_OMIT_SHARED_CACHE - sqlite3VdbeChangeToNoop(v, 2); + sqlite3VdbeChangeToNoop(v, 1); #else - sqlite3VdbeChangeP1(v, 2, iDb); - sqlite3VdbeChangeP2(v, 2, pTab->tnum); - sqlite3VdbeChangeP3(v, 2, flags); - sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); + sqlite3VdbeChangeP1(v, 1, iDb); + sqlite3VdbeChangeP2(v, 1, pTab->tnum); + sqlite3VdbeChangeP3(v, 1, flags); + sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); #endif /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ - sqlite3VdbeChangeToNoop(v, 4 - flags); - sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum); - sqlite3VdbeChangeP3(v, 3 + flags, iDb); + sqlite3VdbeChangeToNoop(v, 3 - flags); + sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum); + sqlite3VdbeChangeP3(v, 2 + flags, iDb); /* Configure the number of columns. Configure the cursor to ** think that the table has one more column than it really @@ -73276,8 +73757,8 @@ SQLITE_API int sqlite3_blob_open( ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ - sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); - sqlite3VdbeChangeP2(v, 7, pTab->nCol); + sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); + sqlite3VdbeChangeP2(v, 6, pTab->nCol); if( !db->mallocFailed ){ pParse->nVar = 1; pParse->nMem = 1; @@ -73862,10 +74343,10 @@ static void vdbeSorterCompare( return; } } - r2->flags |= UNPACKED_PREFIX_MATCH; + assert( r2->default_rc==0 ); } - *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2); + *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0); } /* @@ -75122,9 +75603,12 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ /* ** Call sqlite3WalkExpr() for every expression in Select statement p. ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and -** on the compound select chain, p->pPrior. Invoke the xSelectCallback() -** either before or after the walk of expressions and FROM clause, depending -** on whether pWalker->bSelectDepthFirst is false or true, respectively. +** on the compound select chain, p->pPrior. +** +** If it is not NULL, the xSelectCallback() callback is invoked before +** the walk of the expressions and FROM clause. The xSelectCallback2() +** method, if it is not NULL, is invoked following the walk of the +** expressions and FROM clause. ** ** Return WRC_Continue under normal conditions. Return WRC_Abort if ** there is an abort request. @@ -75134,11 +75618,13 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ */ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ int rc; - if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue; + if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){ + return WRC_Continue; + } rc = WRC_Continue; pWalker->walkerDepth++; while( p ){ - if( !pWalker->bSelectDepthFirst ){ + if( pWalker->xSelectCallback ){ rc = pWalker->xSelectCallback(pWalker, p); if( rc ) break; } @@ -75148,12 +75634,8 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ pWalker->walkerDepth--; return WRC_Abort; } - if( pWalker->bSelectDepthFirst ){ - rc = pWalker->xSelectCallback(pWalker, p); - /* Depth-first search is currently only used for - ** selectAddSubqueryTypeInfo() and that routine always returns - ** WRC_Continue (0). So the following branch is never taken. */ - if( NEVER(rc) ) break; + if( pWalker->xSelectCallback2 ){ + pWalker->xSelectCallback2(pWalker, p); } p = p->pPrior; } @@ -75501,6 +75983,8 @@ static int lookupName( }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ pExpr->iTable = 0; pTab = pParse->pTriggerTab; + }else{ + pTab = 0; } if( pTab ){ @@ -75544,8 +76028,8 @@ static int lookupName( /* ** Perhaps the name is a reference to the ROWID */ - assert( pTab!=0 || cntTab==0 ); - if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) && HasRowid(pTab) ){ + if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol) + && HasRowid(pMatch->pTab) ){ cnt = 1; pExpr->iColumn = -1; /* IMP: R-44911-55124 */ pExpr->affinity = SQLITE_AFF_INTEGER; @@ -77139,16 +77623,25 @@ SQLITE_PRIVATE Expr *sqlite3PExpr( } /* -** Return 1 if an expression must be FALSE in all cases and 0 if the -** expression might be true. This is an optimization. If is OK to -** return 0 here even if the expression really is always false (a -** false negative). But it is a bug to return 1 if the expression -** might be true in some rare circumstances (a false positive.) +** If the expression is always either TRUE or FALSE (respectively), +** then return 1. If one cannot determine the truth value of the +** expression at compile-time return 0. +** +** This is an optimization. If is OK to return 0 here even if +** the expression really is always false or false (a false negative). +** But it is a bug to return 1 if the expression might have different +** boolean values in different circumstances (a false positive.) ** ** Note that if the expression is part of conditional for a ** LEFT JOIN, then we cannot determine at compile-time whether or not ** is it true or false, so always return 0. */ +static int exprAlwaysTrue(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v!=0; +} static int exprAlwaysFalse(Expr *p){ int v = 0; if( ExprHasProperty(p, EP_FromJoin) ) return 0; @@ -77502,6 +77995,33 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ return pNew; } +/* +** Create and return a deep copy of the object passed as the second +** argument. If an OOM condition is encountered, NULL is returned +** and the db->mallocFailed flag set. +*/ +#ifndef SQLITE_OMIT_CTE +static With *withDup(sqlite3 *db, With *p){ + With *pRet = 0; + if( p ){ + int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); + pRet = sqlite3DbMallocZero(db, nByte); + if( pRet ){ + int i; + pRet->nCte = p->nCte; + for(i=0; inCte; i++){ + pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); + pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); + pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); + } + } + } + return pRet; +} +#else +# define withDup(x,y) 0 +#endif + /* ** The following group of routines make deep copies of expressions, ** expression lists, ID lists, and select statements. The copies can @@ -77582,6 +78102,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ pNewItem->regReturn = pOldItem->regReturn; pNewItem->isCorrelated = pOldItem->isCorrelated; pNewItem->viaCoroutine = pOldItem->viaCoroutine; + pNewItem->isRecursive = pOldItem->isRecursive; pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); pNewItem->notIndexed = pOldItem->notIndexed; pNewItem->pIndex = pOldItem->pIndex; @@ -77639,10 +78160,11 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; - pNew->pRightmost = 0; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; + pNew->nSelectRow = p->nSelectRow; + pNew->pWith = withDup(db, p->pWith); return pNew; } #else @@ -77947,24 +78469,6 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ } } -/* -** Generate an OP_IsNull instruction that tests register iReg and jumps -** to location iDest if the value in iReg is NULL. The value in iReg -** was computed by pExpr. If we can look at pExpr at compile-time and -** determine that it can never generate a NULL, then the OP_IsNull operation -** can be omitted. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump( - Vdbe *v, /* The VDBE under construction */ - const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */ - int iReg, /* Test the value in this register for NULL */ - int iDest /* Jump here if the value is null */ -){ - if( sqlite3ExprCanBeNull(pExpr) ){ - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); - } -} - /* ** Return TRUE if the given expression is a constant which would be ** unchanged by OP_Affinity with the affinity given in the second @@ -78161,7 +78665,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ pExpr = p->pEList->a[0].pExpr; iCol = (i16)pExpr->iColumn; - /* Code an OP_VerifyCookie and OP_TableLock for . */ + /* Code an OP_Transaction and OP_TableLock for
    . */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); @@ -78172,9 +78676,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ */ assert(v); if( iCol<0 ){ - int iAddr; - - iAddr = sqlite3CodeOnce(pParse); + int iAddr = sqlite3CodeOnce(pParse); + VdbeCoverage(v); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); eType = IN_INDEX_ROWID; @@ -78199,18 +78702,18 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq && (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None)) ){ - int iAddr = sqlite3CodeOnce(pParse); + int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } + sqlite3VdbeJumpHere(v, iAddr); } } } @@ -78299,7 +78802,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - testAddr = sqlite3CodeOnce(pParse); + testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); } #ifndef SQLITE_OMIT_EXPLAIN @@ -78340,7 +78843,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( */ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); - if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ @@ -78416,6 +78918,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( if( isRowid ){ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); @@ -78539,10 +79042,11 @@ static void sqlite3ExprCodeIN( if( destIfNull==destIfFalse ){ /* Shortcut for the common case where the false and NULL outcomes are ** the same. */ - sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); + sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); }else{ - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); + int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); sqlite3VdbeJumpHere(v, addr1); } @@ -78550,8 +79054,9 @@ static void sqlite3ExprCodeIN( if( eType==IN_INDEX_ROWID ){ /* In this case, the RHS is the ROWID of table b-tree */ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + VdbeCoverage(v); }else{ /* In this case, the RHS is an index b-tree. */ @@ -78572,19 +79077,20 @@ static void sqlite3ExprCodeIN( ** for this particular IN operator. */ sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); - + VdbeCoverage(v); }else{ /* In this branch, the RHS of the IN might contain a NULL and ** the presence of a NULL on the RHS makes a difference in the ** outcome. */ - int j1, j2, j3; + int j1, j2; /* First check to see if the LHS is contained in the RHS. If so, ** then the presence of NULLs in the RHS does not matter, so jump ** over all of the code that follows. */ j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); + VdbeCoverage(v); /* Here we begin generating code that runs if the LHS is not ** contained within the RHS. Generate additional code that @@ -78592,18 +79098,15 @@ static void sqlite3ExprCodeIN( ** jump to destIfNull. If there are no NULLs in the RHS then ** jump to destIfFalse. */ - j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); - j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); - sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull); - sqlite3VdbeJumpHere(v, j3); - sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1); - sqlite3VdbeJumpHere(v, j2); - - /* Jump to the appropriate target depending on whether or not - ** the RHS contains a NULL - */ - sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); + sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v); + j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); /* The OP_Found at the top of this branch jumps here when true, ** causing the overall IN expression evaluation to fall through. @@ -78786,6 +79289,11 @@ SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ */ SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ pParse->iCacheLevel++; +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("PUSH to %d\n", pParse->iCacheLevel); + } +#endif } /* @@ -78799,6 +79307,11 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){ assert( N>0 ); assert( pParse->iCacheLevel>=N ); pParse->iCacheLevel -= N; +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("POP to %d\n", pParse->iCacheLevel); + } +#endif for(i=0, p=pParse->aColCache; iiReg && p->iLevel>pParse->iCacheLevel ){ cacheEntryClear(pParse, p); @@ -78893,6 +79406,11 @@ SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ int i; struct yColCache *p; +#if SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("CLEAR\n"); + } +#endif for(i=0, p=pParse->aColCache; iiReg ){ cacheEntryClear(pParse, p); @@ -79109,22 +79627,16 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) case TK_GE: case TK_NE: case TK_EQ: { - assert( TK_LT==OP_Lt ); - assert( TK_LE==OP_Le ); - assert( TK_GT==OP_Gt ); - assert( TK_GE==OP_Ge ); - assert( TK_EQ==OP_Eq ); - assert( TK_NE==OP_Ne ); - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -79138,6 +79650,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -79154,28 +79668,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) case TK_LSHIFT: case TK_RSHIFT: case TK_CONCAT: { - assert( TK_AND==OP_And ); - assert( TK_OR==OP_Or ); - assert( TK_PLUS==OP_Add ); - assert( TK_MINUS==OP_Subtract ); - assert( TK_REM==OP_Remainder ); - assert( TK_BITAND==OP_BitAnd ); - assert( TK_BITOR==OP_BitOr ); - assert( TK_SLASH==OP_Divide ); - assert( TK_LSHIFT==OP_ShiftLeft ); - assert( TK_RSHIFT==OP_ShiftRight ); - assert( TK_CONCAT==OP_Concat ); - testcase( op==TK_AND ); - testcase( op==TK_OR ); - testcase( op==TK_PLUS ); - testcase( op==TK_MINUS ); - testcase( op==TK_REM ); - testcase( op==TK_BITAND ); - testcase( op==TK_BITOR ); - testcase( op==TK_SLASH ); - testcase( op==TK_LSHIFT ); - testcase( op==TK_RSHIFT ); - testcase( op==TK_CONCAT ); + assert( TK_AND==OP_And ); testcase( op==TK_AND ); + assert( TK_OR==OP_Or ); testcase( op==TK_OR ); + assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); + assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); + assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); + assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND ); + assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR ); + assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH ); + assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT ); + assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT ); + assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); sqlite3VdbeAddOp3(v, op, r2, r1, target); @@ -79207,10 +79710,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) } case TK_BITNOT: case TK_NOT: { - assert( TK_BITNOT==OP_BitNot ); - assert( TK_NOT==OP_Not ); - testcase( op==TK_BITNOT ); - testcase( op==TK_NOT ); + assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT ); + assert( TK_NOT==OP_Not ); testcase( op==TK_NOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); inReg = target; @@ -79220,14 +79721,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) case TK_ISNULL: case TK_NOTNULL: { int addr; - assert( TK_ISNULL==OP_IsNull ); - assert( TK_NOTNULL==OP_NotNull ); - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); addr = sqlite3VdbeAddOp1(v, op, r1); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, addr); break; @@ -79248,7 +79749,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) FuncDef *pDef; /* The function definition object */ int nId; /* Length of the function name in bytes */ const char *zId; /* The function name */ - int constMask = 0; /* Mask of function arguments that are constant */ + u32 constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ @@ -79279,6 +79780,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); for(i=1; ia[i].pExpr, target); @@ -79299,7 +79801,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) for(i=0; ia[i].pExpr) ){ - constMask |= (1<funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); @@ -79415,13 +79918,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) r3 = sqlite3GetTempReg(pParse); r4 = sqlite3GetTempReg(pParse); codeCompare(pParse, pLeft, pRight, OP_Ge, - r1, r2, r3, SQLITE_STOREP2); + r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v); pLItem++; pRight = pLItem->pExpr; sqlite3ReleaseTempReg(pParse, regFree2); r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); testcase( regFree2==0 ); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); + VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); @@ -79588,6 +80092,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( pExpr->affinity==OE_Ignore ){ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); + VdbeCoverage(v); }else{ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, pExpr->affinity, pExpr->u.zToken, 0, 0); @@ -79675,7 +80180,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ ** results in register target. The results are guaranteed to appear ** in register target. */ -SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ +SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ int inReg; assert( target>0 && target<=pParse->nMem ); @@ -79688,7 +80193,20 @@ SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); } } - return target; +} + +/* +** Generate code that will evaluate expression pExpr and store the +** results in register target. The results are guaranteed to appear +** in register target. If the expression is constant, then this routine +** might choose to code the expression at initialization time. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ + if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target, 0); + }else{ + sqlite3ExprCode(pParse, pExpr, target); + } } /* @@ -79703,25 +80221,16 @@ SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ ** times. They are evaluated once and the results of the expression ** are reused. */ -SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ +SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ Vdbe *v = pParse->pVdbe; - int inReg; - inReg = sqlite3ExprCode(pParse, pExpr, target); + int iMem; + assert( target>0 ); - /* The only place, other than this routine, where expressions can be - ** converted to TK_REGISTER is internal subexpressions in BETWEEN and - ** CASE operators. Neither ever calls this routine. And this routine - ** is never called twice on the same expression. Hence it is impossible - ** for the input to this routine to already be a register. Nevertheless, - ** it seems prudent to keep the ALWAYS() in case the conditions above - ** change with future modifications or enhancements. */ - if( ALWAYS(pExpr->op!=TK_REGISTER) ){ - int iMem; - iMem = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); - exprToRegister(pExpr, iMem); - } - return inReg; + assert( pExpr->op!=TK_REGISTER ); + sqlite3ExprCode(pParse, pExpr, target); + iMem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, target, iMem); + exprToRegister(pExpr, iMem); } #if defined(SQLITE_ENABLE_TREE_EXPLAIN) @@ -80029,7 +80538,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ - sqlite3VdbeAddOp2(pParse->pVdbe, copyOp, inReg, target+i); + VdbeOp *pOp; + Vdbe *v = pParse->pVdbe; + if( copyOp==OP_Copy + && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy + && pOp->p1+pOp->p3+1==inReg + && pOp->p2+pOp->p3+1==target+i + ){ + pOp->p3++; + }else{ + sqlite3VdbeAddOp2(v, copyOp, inReg, target+i); + } } } } @@ -80120,8 +80639,8 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); - sqlite3ExprCachePush(pParse); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprCachePush(pParse); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); sqlite3ExprCachePop(pParse, 1); @@ -80130,7 +80649,9 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int case TK_OR: { testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprCachePush(pParse); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3ExprCachePop(pParse, 1); break; } case TK_NOT: { @@ -80144,23 +80665,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { - assert( TK_LT==OP_Lt ); - assert( TK_LE==OP_Le ); - assert( TK_GT==OP_Gt ); - assert( TK_GE==OP_Ge ); - assert( TK_EQ==OP_Eq ); - assert( TK_NE==OP_Ne ); - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -80174,18 +80689,20 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_ISNULL: case TK_NOTNULL: { - assert( TK_ISNULL==OP_IsNull ); - assert( TK_NOTNULL==OP_NotNull ); - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); sqlite3VdbeAddOp2(v, op, r1, dest); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); testcase( regFree1==0 ); break; } @@ -80205,10 +80722,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int } #endif default: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); - sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); - testcase( regFree1==0 ); - testcase( jumpIfNull==0 ); + if( exprAlwaysTrue(pExpr) ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); + }else if( exprAlwaysFalse(pExpr) ){ + /* No-op */ + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); + VdbeCoverage(v); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); + } break; } } @@ -80271,14 +80795,16 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int case TK_AND: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprCachePush(pParse); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3ExprCachePop(pParse, 1); break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); - sqlite3ExprCachePush(pParse); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprCachePush(pParse); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); sqlite3ExprCachePop(pParse, 1); @@ -80295,17 +80821,17 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -80319,16 +80845,18 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_ISNULL: case TK_NOTNULL: { - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); + testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); testcase( regFree1==0 ); break; } @@ -80350,10 +80878,17 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int } #endif default: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); - sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); - testcase( regFree1==0 ); - testcase( jumpIfNull==0 ); + if( exprAlwaysFalse(pExpr) ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); + }else if( exprAlwaysTrue(pExpr) ){ + /* no-op */ + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); + VdbeCoverage(v); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); + } break; } } @@ -80897,8 +81432,8 @@ static void renameTableFunc( assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } @@ -80950,7 +81485,7 @@ static void renameParentFunc( sqlite3Dequote(zParent); if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", - (zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew + (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew ); sqlite3DbFree(db, zOutput); zOutput = zOut; @@ -81036,8 +81571,8 @@ static void renameTriggerFunc( /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } @@ -81289,7 +81824,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( } #endif - /* Begin a transaction and code the VerifyCookie for database iDb. + /* Begin a transaction for database iDb. ** Then modify the schema cookie (since the ALTER TABLE modifies the ** schema). Open a statement transaction if the table is a virtual ** table. @@ -81425,6 +81960,7 @@ SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minForm sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); sqlite3VdbeJumpHere(v, j1); sqlite3ReleaseTempReg(pParse, r1); @@ -82725,6 +83261,7 @@ static void analyzeOneTable( ** */ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto); @@ -82746,6 +83283,7 @@ static void analyzeOneTable( aGotoChng[i] = sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng); aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto); @@ -82792,7 +83330,7 @@ static void analyzeOneTable( sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp); sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, 2+IsStat34); - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); /* Add the entry to the stat1 table. */ callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); @@ -82819,10 +83357,15 @@ static void analyzeOneTable( addrNext = sqlite3VdbeCurrentAddr(v); callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); + VdbeCoverage(v); callStatGet(v, regStat4, STAT_GET_NEQ, regEq); callStatGet(v, regStat4, STAT_GET_NLT, regLt); callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); + /* We know that the regSampleRowid row exists because it was read by + ** the previous loop. Thus the not-found jump of seekOp will never + ** be taken */ + VdbeCoverageNeverTaken(v); #ifdef SQLITE_ENABLE_STAT3 sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pIdx->aiColumn[0], regSample); @@ -82833,10 +83376,10 @@ static void analyzeOneTable( } sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample); #endif - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regTemp, "bbbbbb", 0); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); + sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */ sqlite3VdbeJumpHere(v, addrIsNull); } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ @@ -82853,7 +83396,7 @@ static void analyzeOneTable( if( pOnlyIdx==0 && needTableCnt ){ VdbeComment((v, "%s", pTab->zName)); sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); - jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); + jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); @@ -83453,10 +83996,6 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) if( pExpr ){ if( pExpr->op!=TK_ID ){ rc = sqlite3ResolveExprNames(pName, pExpr); - if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ - sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken); - return SQLITE_ERROR; - } }else{ pExpr->op = TK_STRING; } @@ -84386,6 +84925,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( !pParse->isMultiWrite || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ + while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} sqlite3VdbeAddOp0(v, OP_Halt); /* The cookie mask contains one bit for each database file open. @@ -84394,20 +84934,22 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ ** transaction on each used database and to verify the schema cookie ** on each used database. */ - if( pParse->cookieGoto>0 ){ + if( db->mallocFailed==0 && (pParse->cookieMask || pParse->pConstExpr) ){ yDbMask mask; - int iDb, i, addr; - sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); + int iDb, i; + assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); + sqlite3VdbeJumpHere(v, 0); for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); - if( db->init.busy==0 ){ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - sqlite3VdbeAddOp3(v, OP_VerifyCookie, - iDb, pParse->cookieValue[iDb], - db->aDb[iDb].pSchema->iGeneration); - } + sqlite3VdbeAddOp4Int(v, + OP_Transaction, /* Opcode */ + iDb, /* P1 */ + (mask & pParse->writeMask)!=0, /* P2 */ + pParse->cookieValue[iDb], /* P3 */ + db->aDb[iDb].pSchema->iGeneration /* P4 */ + ); + if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); } #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=0; inVtabLock; i++){ @@ -84428,17 +84970,16 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3AutoincrementBegin(pParse); /* Code constant expressions that where factored out of inner loops */ - addr = pParse->cookieGoto; if( pParse->pConstExpr ){ ExprList *pEL = pParse->pConstExpr; - pParse->cookieGoto = 0; + pParse->okConstFactor = 0; for(i=0; inExpr; i++){ sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); } } /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); + sqlite3VdbeAddOp2(v, OP_Goto, 0, 1); } } @@ -84461,7 +85002,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ pParse->nSet = 0; pParse->nVar = 0; pParse->cookieMask = 0; - pParse->cookieGoto = 0; } /* @@ -85193,7 +85733,7 @@ SQLITE_PRIVATE void sqlite3StartTable( reg3 = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); - j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); + j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); @@ -85697,10 +86237,10 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){ for(j=0; zIdent[j]; j++){ if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break; } - needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID; - if( !needQuote ){ - needQuote = zIdent[j]; - } + needQuote = sqlite3Isdigit(zIdent[0]) + || sqlite3KeywordCode(zIdent, j)!=TK_ID + || zIdent[j]!=0 + || j==0; if( needQuote ) z[i++] = '"'; for(j=0; zIdent[j]; j++){ @@ -86920,27 +87460,27 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ /* Open the table. Loop through all rows of the table, inserting index ** records into the sorter. */ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); regRecord = sqlite3GetTempReg(pParse); - sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 0, &iPartIdxLabel); + sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); sqlite3VdbeResolveLabel(v, iPartIdxLabel); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); - addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); assert( pKey!=0 || db->mallocFailed || pParse->nErr ); if( pIndex->onError!=OE_None && pKey!=0 ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); addr2 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, - pKey->nField - pIndex->nKeyCol); + pKey->nField - pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); }else{ addr2 = sqlite3VdbeCurrentAddr(v); @@ -86949,7 +87489,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); + sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Close, iTab); @@ -87718,7 +88258,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( assert( iStart<=pSrc->nSrc ); /* Allocate additional space if needed */ - if( pSrc->nSrc+nExtra>pSrc->nAlloc ){ + if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ SrcList *pNew; int nAlloc = pSrc->nSrc+nExtra; int nGot; @@ -87730,7 +88270,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( } pSrc = pNew; nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1; - pSrc->nAlloc = (u8)nGot; + pSrc->nAlloc = nGot; } /* Move existing slots that come after the newly inserted slots @@ -87738,7 +88278,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( for(i=pSrc->nSrc-1; i>=iStart; i--){ pSrc->a[i+nExtra] = pSrc->a[i]; } - pSrc->nSrc += (i8)nExtra; + pSrc->nSrc += nExtra; /* Zero the newly allocated slots */ memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra); @@ -88070,59 +88610,26 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ } /* -** Generate VDBE code that will verify the schema cookie and start -** a read-transaction for all named database files. -** -** It is important that all schema cookies be verified and all -** read transactions be started before anything else happens in -** the VDBE program. But this routine can be called after much other -** code has been generated. So here is what we do: -** -** The first time this routine is called, we code an OP_Goto that -** will jump to a subroutine at the end of the program. Then we -** record every database that needs its schema verified in the -** pParse->cookieMask field. Later, after all other code has been -** generated, the subroutine that does the cookie verifications and -** starts the transactions will be coded and the OP_Goto P2 value -** will be made to point to that subroutine. The generation of the -** cookie verification subroutine code happens in sqlite3FinishCoding(). -** -** If iDb<0 then code the OP_Goto only - don't set flag to verify the -** schema on any databases. This can be used to position the OP_Goto -** early in the code, before we know if any database tables will be used. +** Record the fact that the schema cookie will need to be verified +** for database iDb. The code to actually verify the schema cookie +** will occur at the end of the top-level VDBE and will be generated +** later, by sqlite3FinishCoding(). */ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); + sqlite3 *db = pToplevel->db; + yDbMask mask; -#ifndef SQLITE_OMIT_TRIGGER - if( pToplevel!=pParse ){ - /* This branch is taken if a trigger is currently being coded. In this - ** case, set cookieGoto to a non-zero value to show that this function - ** has been called. This is used by the sqlite3ExprCodeConstants() - ** function. */ - pParse->cookieGoto = -1; - } -#endif - if( pToplevel->cookieGoto==0 ){ - Vdbe *v = sqlite3GetVdbe(pToplevel); - if( v==0 ) return; /* This only happens if there was a prior error */ - pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; - } - if( iDb>=0 ){ - sqlite3 *db = pToplevel->db; - yDbMask mask; - - assert( iDbnDb ); - assert( db->aDb[iDb].pBt!=0 || iDb==1 ); - assert( iDbcookieMask & mask)==0 ){ - pToplevel->cookieMask |= mask; - pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; - if( !OMIT_TEMPDB && iDb==1 ){ - sqlite3OpenTempDatabase(pToplevel); - } + assert( iDb>=0 && iDbnDb ); + assert( db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDbcookieMask & mask)==0 ){ + pToplevel->cookieMask |= mask; + pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; + if( !OMIT_TEMPDB && iDb==1 ){ + sqlite3OpenTempDatabase(pToplevel); } } } @@ -88235,9 +88742,9 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint( for(j=0; jnKeyCol; j++){ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3StrAccumAppend(&errMsg, pTab->zName, -1); + sqlite3StrAccumAppendAll(&errMsg, pTab->zName); sqlite3StrAccumAppend(&errMsg, ".", 1); - sqlite3StrAccumAppend(&errMsg, zCol, -1); + sqlite3StrAccumAppendAll(&errMsg, zCol); } zErr = sqlite3StrAccumFinish(&errMsg); sqlite3HaltConstraint(pParse, @@ -88429,8 +88936,9 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ assert( sqlite3KeyInfoIsWriteable(pKey) ); for(i=0; iazColl[i]; - if( NEVER(zColl==0) ) zColl = "BINARY"; - pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl); + assert( zColl!=0 ); + pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : + sqlite3LocateCollSeq(pParse, zColl); pKey->aSortOrder[i] = pIdx->aSortOrder[i]; } if( pParse->nErr ){ @@ -88443,6 +88951,76 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ return sqlite3KeyInfoRef(pIdx->pKeyInfo); } +#ifndef SQLITE_OMIT_CTE +/* +** This routine is invoked once per CTE by the parser while parsing a +** WITH clause. +*/ +SQLITE_PRIVATE With *sqlite3WithAdd( + Parse *pParse, /* Parsing context */ + With *pWith, /* Existing WITH clause, or NULL */ + Token *pName, /* Name of the common-table */ + ExprList *pArglist, /* Optional column name list for the table */ + Select *pQuery /* Query used to initialize the table */ +){ + sqlite3 *db = pParse->db; + With *pNew; + char *zName; + + /* Check that the CTE name is unique within this WITH clause. If + ** not, store an error in the Parse structure. */ + zName = sqlite3NameFromToken(pParse->db, pName); + if( zName && pWith ){ + int i; + for(i=0; inCte; i++){ + if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ + sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName); + } + } + } + + if( pWith ){ + int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); + pNew = sqlite3DbRealloc(db, pWith, nByte); + }else{ + pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); + } + assert( zName!=0 || pNew==0 ); + assert( db->mallocFailed==0 || pNew==0 ); + + if( pNew==0 ){ + sqlite3ExprListDelete(db, pArglist); + sqlite3SelectDelete(db, pQuery); + sqlite3DbFree(db, zName); + pNew = pWith; + }else{ + pNew->a[pNew->nCte].pSelect = pQuery; + pNew->a[pNew->nCte].pCols = pArglist; + pNew->a[pNew->nCte].zName = zName; + pNew->a[pNew->nCte].zErr = 0; + pNew->nCte++; + } + + return pNew; +} + +/* +** Free the contents of the With object passed as the second argument. +*/ +SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){ + if( pWith ){ + int i; + for(i=0; inCte; i++){ + struct Cte *pCte = &pWith->a[i]; + sqlite3ExprListDelete(db, pCte->pCols); + sqlite3SelectDelete(db, pCte->pSelect); + sqlite3DbFree(db, pCte->zName); + } + sqlite3DbFree(db, pWith); + } +} +#endif /* !defined(SQLITE_OMIT_CTE) */ + /************** End of build.c ***********************************************/ /************** Begin file callback.c ****************************************/ /* @@ -88803,7 +89381,6 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction( assert( nArg>=(-2) ); assert( nArg>=(-1) || createFlag==0 ); - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); /* First search for a match amongst the application-defined functions. @@ -89023,10 +89600,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView( SrcList *pFrom; sqlite3 *db = pParse->db; int iDb = sqlite3SchemaToIndex(db, pView->pSchema); - pWhere = sqlite3ExprDup(db, pWhere, 0); pFrom = sqlite3SrcListAppend(db, 0, 0, 0); - if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); @@ -89034,10 +89609,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView( assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); - if( pSel ) pSel->selFlags |= SF_Materialize; - sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pSel, &dest); sqlite3SelectDelete(db, pSel); @@ -89374,7 +89946,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( iKey = ++pParse->nMem; nKey = 0; /* Zero tells OP_Found to use a composite key */ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, - sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); }else{ /* Get the rowid of the row to be deleted and remember it in the RowSet */ @@ -89412,13 +89984,15 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); + VdbeCoverage(v); } }else if( pPk ){ - addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); + addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey); assert( nKey==0 ); /* OP_Found will use a composite key */ }else{ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); + VdbeCoverage(v); assert( nKey==1 ); } @@ -89442,7 +90016,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( okOnePass ){ sqlite3VdbeResolveLabel(v, addrBypass); }else if( pPk ){ - sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); + sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); }else{ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop); @@ -89540,7 +90114,11 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( ** not attempt to delete it or fire any DELETE triggers. */ iLabel = sqlite3VdbeMakeLabel(v); opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - if( !bNoSeek ) sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); + if( !bNoSeek ){ + sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); + VdbeCoverageIf(v, opSeek==OP_NotExists); + VdbeCoverageIf(v, opSeek==OP_NotFound); + } /* If there are any triggers to fire, allocate a range of registers to ** use for the old.* references in the triggers. */ @@ -89562,7 +90140,9 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( ** used by any BEFORE and AFTER triggers that exist. */ sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld); for(iCol=0; iColnCol; iCol++){ - if( mask==0xffffffff || mask&(1<0 */ ){ int i; /* Index loop counter */ - int r1; /* Register holding an index key */ + int r1 = -1; /* Register holding an index key */ int iPartIdxLabel; /* Jump destination for skipping partial index entries */ Index *pIdx; /* Current index */ + Index *pPrior = 0; /* Prior index */ Vdbe *v; /* The prepared statement under construction */ Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */ @@ -89655,10 +90238,12 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( if( aRegIdx!=0 && aRegIdx[i]==0 ) continue; if( pIdx==pPk ) continue; VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); - r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel); + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, + &iPartIdxLabel, pPrior, r1); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); sqlite3VdbeResolveLabel(v, iPartIdxLabel); + pPrior = pIdx; } } @@ -89680,6 +90265,17 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( ** to false or null. If pIdx is not a partial index, *piPartIdxLabel ** will be set to zero which is an empty label that is ignored by ** sqlite3VdbeResolveLabel(). +** +** The pPrior and regPrior parameters are used to implement a cache to +** avoid unnecessary register loads. If pPrior is not NULL, then it is +** a pointer to a different index for which an index key has just been +** computed into register regPrior. If the current pIdx index is generating +** its key into the same sequence of registers and if pPrior and pIdx share +** a column in common, then the register corresponding to that column already +** holds the correct value and the loading of that register is skipped. +** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK +** on a table with multiple indices, and especially with the ROWID or +** PRIMARY KEY columns of the index. */ SQLITE_PRIVATE int sqlite3GenerateIndexKey( Parse *pParse, /* Parsing context */ @@ -89687,14 +90283,15 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( int iDataCur, /* Cursor number from which to take column data */ int regOut, /* Put the new key into this register if not 0 */ int prefixOnly, /* Compute only a unique prefix of the key */ - int *piPartIdxLabel /* OUT: Jump to this label to skip partial index */ + int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */ + Index *pPrior, /* Previously generated index key */ + int regPrior /* Register holding previous generated key */ ){ Vdbe *v = pParse->pVdbe; int j; Table *pTab = pIdx->pTable; int regBase; int nCol; - Index *pPk; if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ @@ -89708,28 +90305,21 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( } nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn; regBase = sqlite3GetTempRange(pParse, nCol); - pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); + if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; for(j=0; jaiColumn[j]; - if( pPk ) idx = sqlite3ColumnOfIndex(pPk, idx); - if( idx<0 || idx==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regBase+j); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iDataCur, idx, regBase+j); - sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1); - } + if( pPrior && pPrior->aiColumn[j]==pIdx->aiColumn[j] ) continue; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pIdx->aiColumn[j], + regBase+j); + /* If the column affinity is REAL but the number is an integer, then it + ** might be stored in the table as an integer (using a compact + ** representation) then converted to REAL by an OP_RealAffinity opcode. + ** But we are getting ready to store this value back into an index, where + ** it should be converted by to INTEGER again. So omit the OP_RealAffinity + ** opcode if it is present */ + sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); } if( regOut ){ - const char *zAff; - if( pTab->pSelect - || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt) - ){ - zAff = 0; - }else{ - zAff = sqlite3IndexAffinityStr(v, pIdx); - } sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); - sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); } sqlite3ReleaseTempRange(pParse, regBase, nCol); return regBase; @@ -89874,7 +90464,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ case SQLITE_INTEGER: { i64 iVal = sqlite3_value_int64(argv[0]); if( iVal<0 ){ - if( (iVal<<1)==0 ){ + if( iVal==SMALLEST_INT64 ){ /* IMP: R-31676-45509 If X is the integer -9223372036854775808 ** then abs(X) throws an integer overflow error since there is no ** equivalent positive 64-bit two complement value. */ @@ -89955,6 +90545,32 @@ static void instrFunc( sqlite3_result_int(context, N); } +/* +** Implementation of the printf() function. +*/ +static void printfFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + PrintfArguments x; + StrAccum str; + const char *zFormat; + int n; + + if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ + x.nArg = argc-1; + x.nUsed = 0; + x.apArg = argv+1; + sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH); + str.db = sqlite3_context_db_handle(context); + sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); + n = str.nChar; + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, + SQLITE_DYNAMIC); + } +} + /* ** Implementation of the substr() function. ** @@ -90728,7 +91344,7 @@ static void charFunc( ){ unsigned char *z, *zOut; int i; - zOut = z = sqlite3_malloc( argc*4 ); + zOut = z = sqlite3_malloc( argc*4+1 ); if( z==0 ){ sqlite3_result_error_nomem(context); return; @@ -91248,11 +91864,11 @@ static void groupConcatStep( zSep = ","; nSep = 1; } - sqlite3StrAccumAppend(pAccum, zSep, nSep); + if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); - sqlite3StrAccumAppend(pAccum, zVal, nVal); + if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); } } static void groupConcatFinalize(sqlite3_context *context){ @@ -91385,6 +92001,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), + FUNCTION(printf, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), @@ -91802,10 +92419,11 @@ static void fkLookupParent( ** search for a matching row in the parent table. */ if( nIncr<0 ){ sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); + VdbeCoverage(v); } for(i=0; inCol; i++){ int iReg = aiCol[i] + regData + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); + sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v); } if( isIgnore==0 ){ @@ -91822,17 +92440,19 @@ static void fkLookupParent( ** will have INTEGER affinity applied to it, which may not be correct. */ sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); + VdbeCoverage(v); /* If the parent table is the same as the child table, and we are about ** to increment the constraint-counter (i.e. this is an INSERT operation), ** then check if the row being inserted matches itself. If so, do not ** increment the constraint-counter. */ if( pTab==pFKey->pFrom && nIncr==1 ){ - sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); + sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); } sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); sqlite3VdbeJumpHere(v, iMustBeInt); @@ -91868,15 +92488,15 @@ static void fkLookupParent( /* The parent key is a composite key that includes the IPK column */ iParent = regData; } - sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); + sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec); - sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); - sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, + sqlite3IndexAffinityStr(v,pIdx), nCol); + sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempRange(pParse, regTemp, nCol); @@ -92014,6 +92634,7 @@ static void fkScanChildren( if( nIncr<0 ){ iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); + VdbeCoverage(v); } /* Create an Expr object representing an SQL expression like: @@ -92176,7 +92797,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa } if( !p ) return; iSkip = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); + sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); } pParse->disableTriggers = 1; @@ -92194,6 +92815,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa */ if( (db->flags & SQLITE_DeferFKs)==0 ){ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, OE_Abort, 0, P4_STATIC, P5_ConstraintFK); } @@ -92353,7 +92975,7 @@ SQLITE_PRIVATE void sqlite3FkCheck( int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; for(i=0; inCol; i++){ int iReg = pFKey->aCol[i].iFrom + regOld + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); + sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); } @@ -92920,10 +93542,16 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ } /* -** Set P4 of the most recently inserted opcode to a column affinity -** string for table pTab. A column affinity string has one character -** for each column indexed by the index, according to the affinity of the -** column: +** Compute the affinity string for table pTab, if it has not already been +** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. +** +** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and +** if iReg>0 then code an OP_Affinity opcode that will set the affinities +** for register iReg and following. Or if affinities exists and iReg==0, +** then just set the P4 operand of the previous opcode (which should be +** an OP_MakeRecord) to the affinity string. +** +** A column affinity string has one character per column: ** ** Character Column affinity ** ------------------------------ @@ -92933,19 +93561,11 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ ** 'd' INTEGER ** 'e' REAL */ -SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ - /* The first time a column affinity string for a particular table - ** is required, it is allocated and populated here. It is then - ** stored as a member of the Table structure for subsequent use. - ** - ** The column affinity string will eventually be deleted by - ** sqlite3DeleteTable() when the Table structure itself is cleaned up. - */ - if( !pTab->zColAff ){ - char *zColAff; - int i; +SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ + int i; + char *zColAff = pTab->zColAff; + if( zColAff==0 ){ sqlite3 *db = sqlite3VdbeDb(v); - zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); if( !zColAff ){ db->mallocFailed = 1; @@ -92955,22 +93575,28 @@ SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ for(i=0; inCol; i++){ zColAff[i] = pTab->aCol[i].affinity; } - zColAff[pTab->nCol] = '\0'; - + do{ + zColAff[i--] = 0; + }while( i>=0 && zColAff[i]==SQLITE_AFF_NONE ); pTab->zColAff = zColAff; } - - sqlite3VdbeChangeP4(v, -1, pTab->zColAff, P4_TRANSIENT); + i = sqlite3Strlen30(zColAff); + if( i ){ + if( iReg ){ + sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); + }else{ + sqlite3VdbeChangeP4(v, -1, zColAff, i); + } + } } /* ** Return non-zero if the table pTab in database iDb or any of its indices -** have been opened at any point in the VDBE program beginning at location -** iStartAddr throught the end of the program. This is used to see if +** have been opened at any point in the VDBE program. This is used to see if ** a statement of the form "INSERT INTO SELECT ..." can -** run without using temporary table for the results of the SELECT. +** run without using a temporary table for the results of the SELECT. */ -static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){ +static int readsTable(Parse *p, int iDb, Table *pTab){ Vdbe *v = sqlite3GetVdbe(p); int i; int iEnd = sqlite3VdbeCurrentAddr(v); @@ -92978,7 +93604,7 @@ static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){ VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0; #endif - for(i=iStartAddr; iopcode==OP_OpenRead && pOp->p3==iDb ){ @@ -93079,14 +93705,14 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); + sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); + sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); - sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); + sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); sqlite3VdbeAddOp0(v, OP_Close); } @@ -93121,25 +93747,16 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ assert( v ); for(p = pParse->pAinc; p; p = p->pNext){ Db *pDb = &db->aDb[p->iDb]; - int j1, j2, j3, j4, j5; + int j1; int iRec; int memId = p->regCtr; iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); - j2 = sqlite3VdbeAddOp0(v, OP_Rewind); - j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); - j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); - sqlite3VdbeAddOp2(v, OP_Next, 0, j3); - sqlite3VdbeJumpHere(v, j2); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); - j5 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, j4); - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeJumpHere(v, j5); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); @@ -93157,97 +93774,6 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ #endif /* SQLITE_OMIT_AUTOINCREMENT */ -/* -** Generate code for a co-routine that will evaluate a subquery one -** row at a time. -** -** The pSelect parameter is the subquery that the co-routine will evaluation. -** Information about the location of co-routine and the registers it will use -** is returned by filling in the pDest object. -** -** Registers are allocated as follows: -** -** pDest->iSDParm The register holding the next entry-point of the -** co-routine. Run the co-routine to its next breakpoint -** by calling "OP_Yield $X" where $X is pDest->iSDParm. -** -** pDest->iSDParm+1 The register holding the "completed" flag for the -** co-routine. This register is 0 if the previous Yield -** generated a new result row, or 1 if the subquery -** has completed. If the Yield is called again -** after this register becomes 1, then the VDBE will -** halt with an SQLITE_INTERNAL error. -** -** pDest->iSdst First result register. -** -** pDest->nSdst Number of result registers. -** -** This routine handles all of the register allocation and fills in the -** pDest structure appropriately. -** -** Here is a schematic of the generated code assuming that X is the -** co-routine entry-point register reg[pDest->iSDParm], that EOF is the -** completed flag reg[pDest->iSDParm+1], and R and S are the range of -** registers that hold the result set, reg[pDest->iSdst] through -** reg[pDest->iSdst+pDest->nSdst-1]: -** -** X <- A -** EOF <- 0 -** goto B -** A: setup for the SELECT -** loop rows in the SELECT -** load results into registers R..S -** yield X -** end loop -** cleanup after the SELECT -** EOF <- 1 -** yield X -** halt-error -** B: -** -** To use this subroutine, the caller generates code as follows: -** -** [ Co-routine generated by this subroutine, shown above ] -** S: yield X -** if EOF goto E -** if skip this row, goto C -** if terminate loop, goto E -** deal with this row -** C: goto S -** E: -*/ -SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){ - int regYield; /* Register holding co-routine entry-point */ - int regEof; /* Register holding co-routine completion flag */ - int addrTop; /* Top of the co-routine */ - int j1; /* Jump instruction */ - int rc; /* Result code */ - Vdbe *v; /* VDBE under construction */ - - regYield = ++pParse->nMem; - regEof = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - addrTop = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */ - VdbeComment((v, "Co-routine entry point")); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ - VdbeComment((v, "Co-routine completion flag")); - sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield); - j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - rc = sqlite3Select(pParse, pSelect, pDest); - assert( pParse->nErr==0 || rc ); - if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM; - if( rc ) return rc; - sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ - sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */ - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); - VdbeComment((v, "End of coroutine")); - sqlite3VdbeJumpHere(v, j1); /* label B: */ - return rc; -} - - - /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ @@ -93310,7 +93836,6 @@ static int xferOptimization( ** and the SELECT clause does not read from
    at any time. ** The generated code follows this template: ** -** EOF <- 0 ** X <- A ** goto B ** A: setup for the SELECT @@ -93319,12 +93844,9 @@ static int xferOptimization( ** yield X ** end loop ** cleanup after the SELECT -** EOF <- 1 -** yield X -** goto A +** end-coroutine X ** B: open write cursor to
    and its indices -** C: yield X -** if EOF goto D +** C: yield X, at EOF goto D ** insert the select result into
    from R..R+n ** goto C ** D: cleanup @@ -93335,7 +93857,6 @@ static int xferOptimization( ** we have to use a intermediate table to store the results of ** the select. The template is like this: ** -** EOF <- 0 ** X <- A ** goto B ** A: setup for the SELECT @@ -93344,12 +93865,9 @@ static int xferOptimization( ** yield X ** end loop ** cleanup after the SELECT -** EOF <- 1 -** yield X -** halt-error +** end co-routine R ** B: open temp table -** L: yield X -** if EOF goto M +** L: yield X, at EOF goto M ** insert row from R..R+n into temp table ** goto L ** M: open write cursor to
    and its indices @@ -93362,7 +93880,6 @@ static int xferOptimization( SQLITE_PRIVATE void sqlite3Insert( Parse *pParse, /* Parser context */ SrcList *pTabList, /* Name of table into which we are inserting */ - ExprList *pList, /* List of values to be inserted */ Select *pSelect, /* A SELECT statement to use as the data source */ IdList *pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ @@ -93380,16 +93897,17 @@ SQLITE_PRIVATE void sqlite3Insert( int iIdxCur = 0; /* First index cursor */ int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ int endOfLoop; /* Label for the end of the insertion loop */ - int useTempTable = 0; /* Store SELECT results in intermediate table */ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ int addrInsTop = 0; /* Jump to label "D" */ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ - int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ - int appendFlag = 0; /* True if the insert is likely to be an append */ - int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ + u8 useTempTable = 0; /* Store SELECT results in intermediate table */ + u8 appendFlag = 0; /* True if the insert is likely to be an append */ + u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ + u8 bIdListInOrder = 1; /* True if IDLIST is in table order */ + ExprList *pList = 0; /* List of VALUES() to be inserted */ /* Register allocations */ int regFromSelect = 0;/* Base register for data coming from SELECT */ @@ -93398,7 +93916,6 @@ SQLITE_PRIVATE void sqlite3Insert( int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ - int regEof = 0; /* Register recording end of SELECT data */ int *aRegIdx = 0; /* One register allocated to each index */ #ifndef SQLITE_OMIT_TRIGGER @@ -93413,6 +93930,17 @@ SQLITE_PRIVATE void sqlite3Insert( goto insert_cleanup; } + /* If the Select object is really just a simple VALUES() list with a + ** single row values (the common case) then keep that one row of values + ** and go ahead and discard the Select object + */ + if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ + pList = pSelect->pEList; + pSelect->pEList = 0; + sqlite3SelectDelete(db, pSelect); + pSelect = 0; + } + /* Locate the table into which we will be inserting new information. */ assert( pTabList->nSrc==1 ); @@ -93490,6 +94018,56 @@ SQLITE_PRIVATE void sqlite3Insert( */ regAutoinc = autoIncBegin(pParse, iDb, pTab); + /* Allocate registers for holding the rowid of the new row, + ** the content of the new row, and the assemblied row record. + */ + regRowid = regIns = pParse->nMem+1; + pParse->nMem += pTab->nCol + 1; + if( IsVirtual(pTab) ){ + regRowid++; + pParse->nMem++; + } + regData = regRowid+1; + + /* If the INSERT statement included an IDLIST term, then make sure + ** all elements of the IDLIST really are columns of the table and + ** remember the column indices. + ** + ** If the table has an INTEGER PRIMARY KEY column and that column + ** is named in the IDLIST, then record in the ipkColumn variable + ** the index into IDLIST of the primary key column. ipkColumn is + ** the index of the primary key as it appears in IDLIST, not as + ** is appears in the original table. (The index of the INTEGER + ** PRIMARY KEY in the original table is pTab->iPKey.) + */ + if( pColumn ){ + for(i=0; inId; i++){ + pColumn->a[i].idx = -1; + } + for(i=0; inId; i++){ + for(j=0; jnCol; j++){ + if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ + pColumn->a[i].idx = j; + if( i!=j ) bIdListInOrder = 0; + if( j==pTab->iPKey ){ + ipkColumn = i; assert( !withoutRowid ); + } + break; + } + } + if( j>=pTab->nCol ){ + if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ + ipkColumn = i; + }else{ + sqlite3ErrorMsg(pParse, "table %S has no column named %s", + pTabList, 0, pColumn->a[i].zName); + pParse->checkSchema = 1; + goto insert_cleanup; + } + } + } + } + /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The @@ -93497,14 +94075,24 @@ SQLITE_PRIVATE void sqlite3Insert( */ if( pSelect ){ /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */ - int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest); - if( rc ) goto insert_cleanup; - - regEof = dest.iSDParm + 1; + int regYield; /* Register holding co-routine entry-point */ + int addrTop; /* Top of the co-routine */ + int rc; /* Result code */ + + regYield = ++pParse->nMem; + addrTop = sqlite3VdbeCurrentAddr(v) + 1; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); + sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + dest.iSdst = bIdListInOrder ? regData : 0; + dest.nSdst = pTab->nCol; + rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; + assert( pParse->nErr==0 || rc ); + if( rc || db->mallocFailed ) goto insert_cleanup; + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); + sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; - assert( dest.nSdst==nColumn ); /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to @@ -93515,7 +94103,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){ + if( pTrigger || readsTable(pParse, iDb, pTab) ){ useTempTable = 1; } @@ -93525,28 +94113,25 @@ SQLITE_PRIVATE void sqlite3Insert( ** here is from the 4th template: ** ** B: open temp table - ** L: yield X - ** if EOF goto M + ** L: yield X, goto M at EOF ** insert row from R..R+n into temp table ** goto L ** M: ... */ int regRec; /* Register to hold packed record */ int regTempRowid; /* Register to hold temp table ROWID */ - int addrTop; /* Label "L" */ - int addrIf; /* Address of jump to M */ + int addrL; /* Label "L" */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof); + addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); - sqlite3VdbeJumpHere(v, addrIf); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrL); + sqlite3VdbeJumpHere(v, addrL); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regTempRowid); } @@ -93567,6 +94152,14 @@ SQLITE_PRIVATE void sqlite3Insert( } } + /* If there is no IDLIST term but the table has an integer primary + ** key, the set the ipkColumn variable to the integer primary key + ** column index in the original table definition. + */ + if( pColumn==0 && nColumn>0 ){ + ipkColumn = pTab->iPKey; + } + /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. */ @@ -93585,52 +94178,6 @@ SQLITE_PRIVATE void sqlite3Insert( sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } - - /* If the INSERT statement included an IDLIST term, then make sure - ** all elements of the IDLIST really are columns of the table and - ** remember the column indices. - ** - ** If the table has an INTEGER PRIMARY KEY column and that column - ** is named in the IDLIST, then record in the ipkColumn variable - ** the index into IDLIST of the primary key column. ipkColumn is - ** the index of the primary key as it appears in IDLIST, not as - ** is appears in the original table. (The index of the INTEGER - ** PRIMARY KEY in the original table is pTab->iPKey.) - */ - if( pColumn ){ - for(i=0; inId; i++){ - pColumn->a[i].idx = -1; - } - for(i=0; inId; i++){ - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ - pColumn->a[i].idx = j; - if( j==pTab->iPKey ){ - ipkColumn = i; assert( !withoutRowid ); - } - break; - } - } - if( j>=pTab->nCol ){ - if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ - ipkColumn = i; - }else{ - sqlite3ErrorMsg(pParse, "table %S has no column named %s", - pTabList, 0, pColumn->a[i].zName); - pParse->checkSchema = 1; - goto insert_cleanup; - } - } - } - } - - /* If there is no IDLIST term but the table has an integer primary - ** key, the set the ipkColumn variable to the integer primary key - ** column index in the original table definition. - */ - if( pColumn==0 && nColumn>0 ){ - ipkColumn = pTab->iPKey; - } /* Initialize the count of rows to be inserted */ @@ -93658,39 +94205,27 @@ SQLITE_PRIVATE void sqlite3Insert( /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 4): ** - ** rewind temp table + ** rewind temp table, if empty goto D ** C: loop over rows of intermediate table ** transfer values form intermediate table into
    ** end loop ** D: ... */ - addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); + addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v); addrCont = sqlite3VdbeCurrentAddr(v); }else if( pSelect ){ /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 3): ** - ** C: yield X - ** if EOF goto D + ** C: yield X, at EOF goto D ** insert the select result into
    from R..R+n ** goto C ** D: ... */ - addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof); + addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); + VdbeCoverage(v); } - /* Allocate registers for holding the rowid of the new row, - ** the content of the new row, and the assemblied row record. - */ - regRowid = regIns = pParse->nMem+1; - pParse->nMem += pTab->nCol + 1; - if( IsVirtual(pTab) ){ - regRowid++; - pParse->nMem++; - } - regData = regRowid+1; - /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); @@ -93714,10 +94249,10 @@ SQLITE_PRIVATE void sqlite3Insert( assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols); } - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); } /* Cannot have triggers on a virtual table. If it were possible, @@ -93751,8 +94286,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** table column affinities. */ if( !isView ){ - sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol); - sqlite3TableAffinityStr(v, pTab); + sqlite3TableAffinity(v, pTab, regCols+1); } /* Fire BEFORE or INSTEAD OF triggers */ @@ -93774,7 +94308,7 @@ SQLITE_PRIVATE void sqlite3Insert( if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+ipkColumn, regRowid); + sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); @@ -93793,14 +94327,14 @@ SQLITE_PRIVATE void sqlite3Insert( if( !appendFlag ){ int j1; if( !IsVirtual(pTab) ){ - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); sqlite3VdbeJumpHere(v, j1); }else{ j1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); + sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); VdbeCoverage(v); } - sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v); } }else if( IsVirtual(pTab) || withoutRowid ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); @@ -93820,8 +94354,9 @@ SQLITE_PRIVATE void sqlite3Insert( /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is read, the rowid will be substituted ** in its place. Hence, fill this column with a NULL to avoid - ** taking up data space with information that will never be used. */ - sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore); + ** taking up data space with information that will never be used. + ** As there may be shallow copies of this value, make it a soft-NULL */ + sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); continue; } if( pColumn==0 ){ @@ -93838,11 +94373,13 @@ SQLITE_PRIVATE void sqlite3Insert( } } if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore); + sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore); }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + if( regFromSelect!=regData ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + } }else{ sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); } @@ -93888,7 +94425,7 @@ SQLITE_PRIVATE void sqlite3Insert( */ sqlite3VdbeResolveLabel(v, endOfLoop); if( useTempTable ){ - sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); + sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ @@ -94055,6 +94592,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int ipkTop = 0; /* Top of the rowid change constraint check */ int ipkBottom = 0; /* Bottom of the rowid change constraint check */ u8 isUpdate; /* True if this is an UPDATE operation */ + u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ + int regRowid = -1; /* Register holding ROWID value */ isUpdate = regOldData!=0; db = pParse->db; @@ -94108,15 +94647,17 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, regNewData+1+i, zMsg, P4_DYNAMIC); sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); + VdbeCoverage(v); break; } case OE_Ignore: { sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); + VdbeCoverage(v); break; } default: { assert( onError==OE_Replace ); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); VdbeCoverage(v); sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); sqlite3VdbeJumpHere(v, j1); break; @@ -94168,6 +94709,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); + VdbeCoverage(v); } /* If the response to a rowid conflict is REPLACE but the response @@ -94187,6 +94730,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Check to see if the new rowid already exists in the table. Skip ** the following conflict logic if it does not. */ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); + VdbeCoverage(v); /* Generate code that deals with a rowid collision */ switch( onError ){ @@ -94265,6 +94809,10 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ + if( bAffinityDone==0 ){ + sqlite3TableAffinity(v, pTab, regNewData+1); + bAffinityDone = 1; + } iThisCur = iIdxCur+ix; addrUniqueOk = sqlite3VdbeMakeLabel(v); @@ -94285,7 +94833,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int iField = pIdx->aiColumn[i]; int x; if( iField<0 || iField==pTab->iPKey ){ + if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ x = regNewData; + regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; }else{ x = iField + regNewData + 1; } @@ -94293,7 +94843,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); - sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT); VdbeComment((v, "for %s", pIdx->zName)); sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn); @@ -94321,51 +94870,58 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, - regIdx, pIdx->nKeyCol); + regIdx, pIdx->nKeyCol); VdbeCoverage(v); /* Generate code to handle collisions */ regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); - /* Conflict only if the rowid of the existing index entry - ** is different from old-rowid */ - if( isUpdate ){ - sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); - } - }else{ - int x; - /* Extract the PRIMARY KEY from the end of the index entry and - ** store it in registers regR..regR+nPk-1 */ - if( (isUpdate || onError==OE_Replace) && pIdx!=pPk ){ - for(i=0; inKeyCol; i++){ - x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); - sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); - VdbeComment((v, "%s.%s", pTab->zName, - pTab->aCol[pPk->aiColumn[i]].zName)); - } - } - if( isUpdate ){ - /* If currently processing the PRIMARY KEY of a WITHOUT ROWID - ** table, only conflict if the new PRIMARY KEY values are actually - ** different from the old. - ** - ** For a UNIQUE index, only conflict if the PRIMARY KEY values - ** of the matched index row are different from the original PRIMARY - ** KEY values of this row before the update. */ - int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; - int op = OP_Ne; - int regCmp = (pIdx->autoIndex==2 ? regIdx : regR); - - for(i=0; inKeyCol; i++){ - char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); - x = pPk->aiColumn[i]; - if( i==(pPk->nKeyCol-1) ){ - addrJump = addrUniqueOk; - op = OP_Eq; + if( isUpdate || onError==OE_Replace ){ + if( HasRowid(pTab) ){ + sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); + /* Conflict only if the rowid of the existing index entry + ** is different from old-rowid */ + if( isUpdate ){ + sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); + VdbeCoverage(v); + } + }else{ + int x; + /* Extract the PRIMARY KEY from the end of the index entry and + ** store it in registers regR..regR+nPk-1 */ + if( pIdx!=pPk ){ + for(i=0; inKeyCol; i++){ + x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); + sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); + VdbeComment((v, "%s.%s", pTab->zName, + pTab->aCol[pPk->aiColumn[i]].zName)); + } + } + if( isUpdate ){ + /* If currently processing the PRIMARY KEY of a WITHOUT ROWID + ** table, only conflict if the new PRIMARY KEY values are actually + ** different from the old. + ** + ** For a UNIQUE index, only conflict if the PRIMARY KEY values + ** of the matched index row are different from the original PRIMARY + ** KEY values of this row before the update. */ + int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; + int op = OP_Ne; + int regCmp = (pIdx->autoIndex==2 ? regIdx : regR); + + for(i=0; inKeyCol; i++){ + char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); + x = pPk->aiColumn[i]; + if( i==(pPk->nKeyCol-1) ){ + addrJump = addrUniqueOk; + op = OP_Eq; + } + sqlite3VdbeAddOp4(v, op, + regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ + ); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); + VdbeCoverageIf(v, op==OP_Eq); + VdbeCoverageIf(v, op==OP_Ne); } - sqlite3VdbeAddOp4(v, op, - regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ - ); } } } @@ -94436,14 +94992,17 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( int regData; /* Content registers (after the rowid) */ int regRec; /* Register holding assemblied record for the table */ int i; /* Loop counter */ + u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */ v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( aRegIdx[i]==0 ) continue; + bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]); pik_flags = 0; @@ -94458,7 +95017,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); - sqlite3TableAffinityStr(v, pTab); + if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); if( pParse->nested ){ pik_flags = 0; @@ -94664,6 +95223,12 @@ static int xferOptimization( if( pSelect==0 ){ return 0; /* Must be of the form INSERT INTO ... SELECT ... */ } + if( pParse->pWith || pSelect->pWith ){ + /* Do not attempt to process this query if there are an WITH clauses + ** attached to it. Proceeding may generate a false "no such table: xxx" + ** error if pSelect reads from a CTE named "xxx". */ + return 0; + } if( sqlite3TriggerList(pParse, pDest) ){ return 0; /* tab1 must not have triggers */ } @@ -94821,16 +95386,17 @@ static int xferOptimization( ** ** (3) onError is something other than OE_Abort and OE_Rollback. */ - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); - emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + VdbeCoverage(v); sqlite3RowidConstraint(pParse, onError, pDest); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); @@ -94844,7 +95410,7 @@ static int xferOptimization( sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ @@ -94863,15 +95429,15 @@ static int xferOptimization( sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); } - sqlite3VdbeJumpHere(v, emptySrcTest); + if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); sqlite3ReleaseTempReg(pParse, regRowid); sqlite3ReleaseTempReg(pParse, regData); if( emptyDestTest ){ @@ -97105,6 +97671,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** size of historical compatibility. */ case PragTyp_DEFAULT_CACHE_SIZE: { + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList getCacheSize[] = { { OP_Transaction, 0, 0, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ @@ -97122,7 +97689,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); pParse->nMem += 2; - addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, iDb); sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); @@ -97367,6 +97934,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** file. Before writing to meta[6], check that meta[3] indicates ** that this really is an auto-vacuum capable database. */ + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList setMeta6[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, @@ -97376,7 +97944,7 @@ SQLITE_PRIVATE void sqlite3Pragma( { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ }; int iAddr; - iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); + iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb); sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); @@ -97402,10 +97970,10 @@ SQLITE_PRIVATE void sqlite3Pragma( } sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); - addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); + addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_ResultRow, 1); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); break; } @@ -97976,7 +98544,7 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( pParse->nErr>0 || pFK==0 ); if( pFK ) break; if( pParse->nTabnTab = i; - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); pIdx = 0; @@ -97992,26 +98560,26 @@ SQLITE_PRIVATE void sqlite3Pragma( if( iKey!=pTab->iPKey ){ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); - sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, - sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, + sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } - sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); + sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ for(j=0; jnCol; j++){ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); } if( pParent ){ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); - sqlite3VdbeChangeP4(v, -1, - sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, + sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); + VdbeCoverage(v); } } sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); @@ -98022,7 +98590,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeResolveLabel(v, addrOk); sqlite3DbFree(db, aiCols); } - sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); + sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrTop); } } @@ -98069,6 +98637,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** messages have been generated, output OK. Otherwise output the ** error message */ + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ { OP_IfNeg, 1, 0, 0}, /* 1 */ @@ -98117,6 +98686,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3CodeVerifySchema(pParse, i); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); @@ -98148,7 +98718,7 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Do the b-tree integrity checks */ sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); sqlite3VdbeChangeP5(v, (u8)i); - addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); + addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); @@ -98162,12 +98732,15 @@ SQLITE_PRIVATE void sqlite3Pragma( for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx, *pPk; + Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; + int r1 = -1; if( pTab->pIndex==0 ) continue; pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); sqlite3ExprCacheClear(pParse); @@ -98178,16 +98751,17 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ } pParse->nMem = MAX(pParse->nMem, 8+j); - sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2, jmp3, jmp4; - int r1; if( pPk==pIdx ) continue; - r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3); + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, + pPrior, r1); + pPrior = pIdx; sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1, - pIdx->nColumn); + pIdx->nColumn); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC); sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); @@ -98197,13 +98771,13 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); - jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); + jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); sqlite3VdbeAddOp0(v, OP_Halt); sqlite3VdbeJumpHere(v, jmp4); sqlite3VdbeJumpHere(v, jmp2); sqlite3VdbeResolveLabel(v, jmp3); } - sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); + sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); #ifndef SQLITE_OMIT_BTREECOUNT sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, @@ -98211,10 +98785,11 @@ SQLITE_PRIVATE void sqlite3Pragma( for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ if( pPk==pIdx ) continue; addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); - sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); + sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); @@ -98223,7 +98798,7 @@ SQLITE_PRIVATE void sqlite3Pragma( #endif /* SQLITE_OMIT_BTREECOUNT */ } } - addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); + addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); sqlite3VdbeChangeP2(v, addr, -mxErr); sqlite3VdbeJumpHere(v, addr+1); sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); @@ -98361,7 +98936,7 @@ SQLITE_PRIVATE void sqlite3Pragma( { OP_Integer, 0, 1, 0}, /* 1 */ { OP_SetCookie, 0, 0, 1}, /* 2 */ }; - int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); + int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); sqlite3VdbeChangeP1(v, addr+2, iDb); @@ -98373,7 +98948,7 @@ SQLITE_PRIVATE void sqlite3Pragma( { OP_ReadCookie, 0, 1, 0}, /* 1 */ { OP_ResultRow, 1, 1, 0} }; - int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); + int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, iDb); sqlite3VdbeChangeP3(v, addr+1, iCookie); @@ -99112,7 +99687,11 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ ** Free all memory allocations in the pParse object */ SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ - if( pParse ) sqlite3ExprListDelete(pParse->db, pParse->pConstExpr); + if( pParse ){ + sqlite3 *db = pParse->db; + sqlite3DbFree(db, pParse->aLabel); + sqlite3ExprListDelete(db, pParse->pConstExpr); + } } /* @@ -99496,6 +100075,7 @@ static void clearSelect(sqlite3 *db, Select *p){ sqlite3SelectDelete(db, p->pPrior); sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pOffset); + sqlite3WithDelete(db, p->pWith); } /* @@ -99575,6 +100155,14 @@ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ } } +/* +** Return a pointer to the right-most SELECT statement in a compound. +*/ +static Select *findRightmost(Select *p){ + while( p->pNext ) p = p->pNext; + return p; +} + /* ** Given 1 to 3 identifiers preceding the JOIN keyword, determine the ** type of join. Return an integer constant that expresses that type @@ -99913,7 +100501,7 @@ static void pushOntoSorter( }else{ iLimit = pSelect->iLimit; } - addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); + addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); addr2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); @@ -99928,13 +100516,13 @@ static void pushOntoSorter( */ static void codeOffset( Vdbe *v, /* Generate code into this VM */ - Select *p, /* The SELECT statement being coded */ + int iOffset, /* Register holding the offset counter */ int iContinue /* Jump here to skip the current record */ ){ - if( p->iOffset && iContinue!=0 ){ + if( iOffset>0 && iContinue!=0 ){ int addr; - sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); - addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset); + sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1); + addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); VdbeComment((v, "skip OFFSET records")); sqlite3VdbeJumpHere(v, addr); @@ -99962,7 +100550,7 @@ static void codeDistinct( v = pParse->pVdbe; r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); + sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); sqlite3ReleaseTempReg(pParse, r1); @@ -100009,17 +100597,16 @@ struct DistinctCtx { ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** -** If srcTab and nColumn are both zero, then the pEList expressions -** are evaluated in order to get the data for this row. If nColumn>0 -** then data is pulled from srcTab and pEList is used only to get the -** datatypes for each column. +** If srcTab is negative, then the pEList expressions +** are evaluated in order to get the data for this row. If srcTab is +** zero or more, then data is pulled from srcTab and pEList is used only +** to get number columns and the datatype for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ - int nColumn, /* Number of columns in the source table */ ExprList *pOrderBy, /* If not NULL, sort results using this key */ DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ SelectDest *pDest, /* How to dispose of the results */ @@ -100035,49 +100622,47 @@ static void selectInnerLoop( int nResultCol; /* Number of result columns */ assert( v ); - if( NEVER(v==0) ) return; assert( pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; if( pOrderBy==0 && !hasDistinct ){ - codeOffset(v, p, iContinue); + codeOffset(v, p->iOffset, iContinue); } /* Pull the requested columns. */ - if( nColumn>0 ){ - nResultCol = nColumn; - }else{ - nResultCol = pEList->nExpr; - } + nResultCol = pEList->nExpr; + if( pDest->iSdst==0 ){ pDest->iSdst = pParse->nMem+1; - pDest->nSdst = nResultCol; pParse->nMem += nResultCol; - }else{ - assert( pDest->nSdst==nResultCol ); + }else if( pDest->iSdst+nResultCol > pParse->nMem ){ + /* This is an error condition that can result, for example, when a SELECT + ** on the right-hand side of an INSERT contains more result columns than + ** there are columns in the table on the left. The error will be caught + ** and reported later. But we need to make sure enough memory is allocated + ** to avoid other spurious errors in the meantime. */ + pParse->nMem += nResultCol; } + pDest->nSdst = nResultCol; regResult = pDest->iSdst; - if( nColumn>0 ){ - for(i=0; i=0 ){ + for(i=0; ia[i].zName)); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pEList, regResult, - (eDest==SRT_Output)?SQLITE_ECEL_DUP:0); + (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0); } - nColumn = nResultCol; /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ - assert( pEList!=0 ); - assert( pEList->nExpr==nColumn ); switch( pDistinct->eTnctType ){ case WHERE_DISTINCT_ORDERED: { VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ @@ -100086,7 +100671,7 @@ static void selectInnerLoop( /* Allocate space for the previous row */ regPrev = pParse->nMem+1; - pParse->nMem += nColumn; + pParse->nMem += nResultCol; /* Change the OP_OpenEphemeral coded earlier to an OP_Null ** sets the MEM_Cleared bit on the first register of the @@ -100100,19 +100685,21 @@ static void selectInnerLoop( pOp->p1 = 1; pOp->p2 = regPrev; - iJump = sqlite3VdbeCurrentAddr(v) + nColumn; - for(i=0; ia[i].pExpr); - if( ieTnctType==WHERE_DISTINCT_UNORDERED ); - codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult); + codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult); break; } } if( pOrderBy==0 ){ - codeOffset(v, p, iContinue); + codeOffset(v, p->iOffset, iContinue); } } @@ -100140,7 +100727,7 @@ static void selectInnerLoop( case SRT_Union: { int r1; r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; @@ -100151,19 +100738,33 @@ static void selectInnerLoop( ** the temporary table iParm. */ case SRT_Except: { - sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn); + sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol); break; } -#endif +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ /* Store the result as data using a unique key. */ + case SRT_DistTable: case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); +#ifndef SQLITE_OMIT_CTE + if( eDest==SRT_DistTable ){ + /* If the destination is DistTable, then cursor (iParm+1) is open + ** on an ephemeral index. If the current row is already present + ** in the index, do not write it to the output. If not, add the + ** current row to the index and proceed with writing it to the + ** output table as well. */ + int addr = sqlite3VdbeCurrentAddr(v) + 4; + sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1); + assert( pOrderBy==0 ); + } +#endif if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, r1); }else{ @@ -100183,7 +100784,7 @@ static void selectInnerLoop( ** item into the set table with bogus data. */ case SRT_Set: { - assert( nColumn==1 ); + assert( nResultCol==1 ); pDest->affSdst = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst); if( pOrderBy ){ @@ -100215,7 +100816,7 @@ static void selectInnerLoop( ** of the scan loop. */ case SRT_Mem: { - assert( nColumn==1 ); + assert( nResultCol==1 ); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ @@ -100226,28 +100827,73 @@ static void selectInnerLoop( } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ - /* Send the data to the callback function or to a subroutine. In the - ** case of a subroutine, the subroutine itself is responsible for - ** popping the data from the stack. - */ - case SRT_Coroutine: - case SRT_Output: { + case SRT_Coroutine: /* Send data to a co-routine */ + case SRT_Output: { /* Return the results */ testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); - sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); + sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); } break; } +#ifndef SQLITE_OMIT_CTE + /* Write the results into a priority queue that is order according to + ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an + ** index with pSO->nExpr+2 columns. Build a key using pSO for the first + ** pSO->nExpr columns, then make sure all keys are unique by adding a + ** final OP_Sequence column. The last column is the record as a blob. + */ + case SRT_DistQueue: + case SRT_Queue: { + int nKey; + int r1, r2, r3; + int addrTest = 0; + ExprList *pSO; + pSO = pDest->pOrderBy; + assert( pSO ); + nKey = pSO->nExpr; + r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3GetTempRange(pParse, nKey+2); + r3 = r2+nKey+1; + if( eDest==SRT_DistQueue ){ + /* If the destination is DistQueue, then cursor (iParm+1) is open + ** on a second ephemeral index that holds all values every previously + ** added to the queue. */ + addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, + regResult, nResultCol); + VdbeCoverage(v); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); + if( eDest==SRT_DistQueue ){ + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + } + for(i=0; ia[i].u.x.iOrderByCol - 1, + r2+i); + } + sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); + sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempRange(pParse, r2, nKey+2); + break; + } +#endif /* SQLITE_OMIT_CTE */ + + + #if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call @@ -100266,7 +100912,7 @@ static void selectInnerLoop( ** the output for us. */ if( pOrderBy==0 && p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); + sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); } } @@ -100336,7 +100982,7 @@ SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; } ** function is responsible for seeing that this structure is eventually ** freed. */ -static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ +static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList, int nExtra){ int nExpr; KeyInfo *pInfo; struct ExprList_item *pItem; @@ -100344,7 +100990,7 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ int i; nExpr = pList->nExpr; - pInfo = sqlite3KeyInfoAlloc(db, nExpr, 1); + pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra, 1); if( pInfo ){ assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=0, pItem=pList->a; inTab++; sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); - codeOffset(v, p, addrContinue); + VdbeCoverage(v); + codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow); sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); }else{ - addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); - codeOffset(v, p, addrContinue); + addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); + codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow); } switch( eDest ){ @@ -100548,9 +101195,9 @@ static void generateSortTail( */ sqlite3VdbeResolveLabel(v, addrContinue); if( p->selFlags & SF_UseSorter ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); + sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v); }else{ - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v); } sqlite3VdbeResolveLabel(v, addrBreak); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ @@ -100670,7 +101317,7 @@ static const char *columnTypeImpl( sNC.pParse = pNC->pParse; zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); } - }else if( ALWAYS(pTab->pSchema) ){ + }else if( pTab->pSchema ){ /* A real table */ assert( !pS ); if( iCol<0 ) iCol = pTab->iPKey; @@ -100831,8 +101478,9 @@ static void generateColumnNames( sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); } }else{ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); + const char *z = pEList->a[i].zSpan; + z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC); } } generateColumnTypes(pParse, pTabList, pEList); @@ -100920,7 +101568,7 @@ static int selectColumnsFromExprList( char *zNewName; int k; for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} - if( zName[k]==':' ) nName = k; + if( k>=0 && zName[k]==':' ) nName = k; zName[nName] = 0; zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); sqlite3DbFree(db, zName); @@ -101032,12 +101680,14 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ Vdbe *v = pParse->pVdbe; if( v==0 ){ - v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); -#ifndef SQLITE_OMIT_TRACE - if( v ){ - sqlite3VdbeAddOp0(v, OP_Trace); + v = pParse->pVdbe = sqlite3VdbeCreate(pParse); + if( v ) sqlite3VdbeAddOp0(v, OP_Init); + if( pParse->pToplevel==0 + && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) + ){ + pParse->okConstFactor = 1; } -#endif + } return v; } @@ -101054,8 +101704,13 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ ** ** This routine changes the values of iLimit and iOffset only if ** a limit or offset is defined by pLimit and pOffset. iLimit and -** iOffset should have been preset to appropriate default values -** (usually but not always -1) prior to calling this routine. +** iOffset should have been preset to appropriate default values (zero) +** prior to calling this routine. +** +** The iOffset register (if it exists) is initialized to the value +** of the OFFSET. The iLimit register is initialized to LIMIT. Register +** iOffset+1 is initialized to LIMIT+OFFSET. +** ** Only if pLimit!=0 or pOffset!=0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple @@ -101079,7 +101734,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ if( p->pLimit ){ p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); - if( NEVER(v==0) ) return; /* VDBE should have already been allocated */ + assert( v!=0 ); if( sqlite3ExprIsInteger(p->pLimit, &n) ){ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment((v, "LIMIT counter")); @@ -101090,22 +101745,22 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ } }else{ sqlite3ExprCode(pParse, p->pLimit, iLimit); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); + sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v); } if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; pParse->nMem++; /* Allocate an extra register for limit+offset */ sqlite3ExprCode(pParse, p->pOffset, iOffset); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); VdbeComment((v, "OFFSET counter")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); VdbeComment((v, "LIMIT+OFFSET")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); sqlite3VdbeJumpHere(v, addr1); } @@ -101134,9 +101789,209 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ } return pRet; } -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ -/* Forward reference */ +/* +** The select statement passed as the second parameter is a compound SELECT +** with an ORDER BY clause. This function allocates and returns a KeyInfo +** structure suitable for implementing the ORDER BY. +** +** Space to hold the KeyInfo structure is obtained from malloc. The calling +** function is responsible for ensuring that this structure is eventually +** freed. +*/ +static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ + ExprList *pOrderBy = p->pOrderBy; + int nOrderBy = p->pOrderBy->nExpr; + sqlite3 *db = pParse->db; + KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); + if( pRet ){ + int i; + for(i=0; ia[i]; + Expr *pTerm = pItem->pExpr; + CollSeq *pColl; + + if( pTerm->flags & EP_Collate ){ + pColl = sqlite3ExprCollSeq(pParse, pTerm); + }else{ + pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1); + if( pColl==0 ) pColl = db->pDfltColl; + pOrderBy->a[i].pExpr = + sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); + } + assert( sqlite3KeyInfoIsWriteable(pRet) ); + pRet->aColl[i] = pColl; + pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder; + } + } + + return pRet; +} + +#ifndef SQLITE_OMIT_CTE +/* +** This routine generates VDBE code to compute the content of a WITH RECURSIVE +** query of the form: +** +** AS ( UNION [ALL] ) +** \___________/ \_______________/ +** p->pPrior p +** +** +** There is exactly one reference to the recursive-table in the FROM clause +** of recursive-query, marked with the SrcList->a[].isRecursive flag. +** +** The setup-query runs once to generate an initial set of rows that go +** into a Queue table. Rows are extracted from the Queue table one by +** one. Each row extracted from Queue is output to pDest. Then the single +** extracted row (now in the iCurrent table) becomes the content of the +** recursive-table for a recursive-query run. The output of the recursive-query +** is added back into the Queue table. Then another row is extracted from Queue +** and the iteration continues until the Queue table is empty. +** +** If the compound query operator is UNION then no duplicate rows are ever +** inserted into the Queue table. The iDistinct table keeps a copy of all rows +** that have ever been inserted into Queue and causes duplicates to be +** discarded. If the operator is UNION ALL, then duplicates are allowed. +** +** If the query has an ORDER BY, then entries in the Queue table are kept in +** ORDER BY order and the first entry is extracted for each cycle. Without +** an ORDER BY, the Queue table is just a FIFO. +** +** If a LIMIT clause is provided, then the iteration stops after LIMIT rows +** have been output to pDest. A LIMIT of zero means to output no rows and a +** negative LIMIT means to output all rows. If there is also an OFFSET clause +** with a positive value, then the first OFFSET outputs are discarded rather +** than being sent to pDest. The LIMIT count does not begin until after OFFSET +** rows have been skipped. +*/ +static void generateWithRecursiveQuery( + Parse *pParse, /* Parsing context */ + Select *p, /* The recursive SELECT to be coded */ + SelectDest *pDest /* What to do with query results */ +){ + SrcList *pSrc = p->pSrc; /* The FROM clause of the recursive query */ + int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */ + Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ + Select *pSetup = p->pPrior; /* The setup query */ + int addrTop; /* Top of the loop */ + int addrCont, addrBreak; /* CONTINUE and BREAK addresses */ + int iCurrent = 0; /* The Current table */ + int regCurrent; /* Register holding Current table */ + int iQueue; /* The Queue table */ + int iDistinct = 0; /* To ensure unique results if UNION */ + int eDest = SRT_Table; /* How to write to Queue */ + SelectDest destQueue; /* SelectDest targetting the Queue table */ + int i; /* Loop counter */ + int rc; /* Result code */ + ExprList *pOrderBy; /* The ORDER BY clause */ + Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */ + int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ + + /* Obtain authorization to do a recursive query */ + if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; + + /* Process the LIMIT and OFFSET clauses, if they exist */ + addrBreak = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, addrBreak); + pLimit = p->pLimit; + pOffset = p->pOffset; + regLimit = p->iLimit; + regOffset = p->iOffset; + p->pLimit = p->pOffset = 0; + p->iLimit = p->iOffset = 0; + pOrderBy = p->pOrderBy; + + /* Locate the cursor number of the Current table */ + for(i=0; ALWAYS(inSrc); i++){ + if( pSrc->a[i].isRecursive ){ + iCurrent = pSrc->a[i].iCursor; + break; + } + } + + /* Allocate cursors numbers for Queue and Distinct. The cursor number for + ** the Distinct table must be exactly one greater than Queue in order + ** for the SRT_DistTable and SRT_DistQueue destinations to work. */ + iQueue = pParse->nTab++; + if( p->op==TK_UNION ){ + eDest = pOrderBy ? SRT_DistQueue : SRT_DistTable; + iDistinct = pParse->nTab++; + }else{ + eDest = pOrderBy ? SRT_Queue : SRT_Table; + } + sqlite3SelectDestInit(&destQueue, eDest, iQueue); + + /* Allocate cursors for Current, Queue, and Distinct. */ + regCurrent = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol); + if( pOrderBy ){ + KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0, + (char*)pKeyInfo, P4_KEYINFO); + destQueue.pOrderBy = pOrderBy; + }else{ + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol); + } + VdbeComment((v, "Queue table")); + if( iDistinct ){ + p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0); + p->selFlags |= SF_UsesEphemeral; + } + + /* Detach the ORDER BY clause from the compound SELECT */ + p->pOrderBy = 0; + + /* Store the results of the setup-query in Queue. */ + pSetup->pNext = 0; + rc = sqlite3Select(pParse, pSetup, &destQueue); + pSetup->pNext = p; + if( rc ) goto end_of_recursive_query; + + /* Find the next row in the Queue and output that row */ + addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v); + + /* Transfer the next row in Queue over to Current */ + sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */ + if( pOrderBy ){ + sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent); + }else{ + sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent); + } + sqlite3VdbeAddOp1(v, OP_Delete, iQueue); + + /* Output the single row in Current */ + addrCont = sqlite3VdbeMakeLabel(v); + codeOffset(v, regOffset, addrCont); + selectInnerLoop(pParse, p, p->pEList, iCurrent, + 0, 0, pDest, addrCont, addrBreak); + if( regLimit ){ + sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); + VdbeCoverage(v); + } + sqlite3VdbeResolveLabel(v, addrCont); + + /* Execute the recursive SELECT taking the single row in Current as + ** the value for the recursive-table. Store the results in the Queue. + */ + p->pPrior = 0; + sqlite3Select(pParse, p, &destQueue); + assert( p->pPrior==0 ); + p->pPrior = pSetup; + + /* Keep running the loop until the Queue is empty */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); + sqlite3VdbeResolveLabel(v, addrBreak); + +end_of_recursive_query: + p->pOrderBy = pOrderBy; + p->pLimit = pLimit; + p->pOffset = pOffset; + return; +} +#endif /* SQLITE_OMIT_CTE */ + +/* Forward references */ static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ @@ -101144,7 +101999,6 @@ static int multiSelectOrderBy( ); -#ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine is called to process a compound query form from ** two or more separate queries using UNION, UNION ALL, EXCEPT, or @@ -101188,18 +102042,17 @@ static int multiSelect( Select *pDelete = 0; /* Chain of simple selects to delete */ sqlite3 *db; /* Database connection */ #ifndef SQLITE_OMIT_EXPLAIN - int iSub1; /* EQP id of left-hand query */ - int iSub2; /* EQP id of right-hand query */ + int iSub1 = 0; /* EQP id of left-hand query */ + int iSub2 = 0; /* EQP id of right-hand query */ #endif /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. */ assert( p && p->pPrior ); /* Calling function guarantees this much */ + assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION ); db = pParse->db; pPrior = p->pPrior; - assert( pPrior->pRightmost!=pPrior ); - assert( pPrior->pRightmost==p->pRightmost ); dest = *pDest; if( pPrior->pOrderBy ){ sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", @@ -101241,11 +102094,17 @@ static int multiSelect( goto multi_select_end; } +#ifndef SQLITE_OMIT_CTE + if( p->selFlags & SF_Recursive ){ + generateWithRecursiveQuery(pParse, p, &dest); + }else +#endif + /* Compound SELECTs that have an ORDER BY clause are handled separately. */ if( p->pOrderBy ){ return multiSelectOrderBy(pParse, p, pDest); - } + }else /* Generate code for the left and right SELECT statements. */ @@ -101269,7 +102128,7 @@ static int multiSelect( p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); + addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); } explainSetInteger(iSub2, pParse->iNextSelectId); @@ -101301,12 +102160,10 @@ static int multiSelect( testcase( p->op==TK_EXCEPT ); testcase( p->op==TK_UNION ); priorOp = SRT_Union; - if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){ + if( dest.eDest==priorOp ){ /* We can reuse a temporary table generated by a SELECT to our ** right. */ - assert( p->pRightmost!=p ); /* Can only happen for leftward elements - ** of a 3-way or more compound */ assert( p->pLimit==0 ); /* Not allowed on leftward elements */ assert( p->pOffset==0 ); /* Not allowed on leftward elements */ unionTab = dest.iSDParm; @@ -101319,7 +102176,7 @@ static int multiSelect( addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); assert( p->addrOpenEphm[0] == -1 ); p->addrOpenEphm[0] = addr; - p->pRightmost->selFlags |= SF_UsesEphemeral; + findRightmost(p)->selFlags |= SF_UsesEphemeral; assert( p->pEList ); } @@ -101378,12 +102235,12 @@ static int multiSelect( iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, + selectInnerLoop(pParse, p, p->pEList, unionTab, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); } @@ -101408,7 +102265,7 @@ static int multiSelect( addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); assert( p->addrOpenEphm[0] == -1 ); p->addrOpenEphm[0] = addr; - p->pRightmost->selFlags |= SF_UsesEphemeral; + findRightmost(p)->selFlags |= SF_UsesEphemeral; assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". @@ -101453,15 +102310,15 @@ static int multiSelect( iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, + selectInnerLoop(pParse, p, p->pEList, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); @@ -101487,7 +102344,7 @@ static int multiSelect( CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ int nCol; /* Number of columns in result set */ - assert( p->pRightmost==p ); + assert( p->pNext==0 ); nCol = p->pEList->nExpr; pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); if( !pKeyInfo ){ @@ -101568,10 +102425,10 @@ static int generateOutputSubroutine( */ if( regPrev ){ int j1, j2; - j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); + j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); + sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); @@ -101580,7 +102437,7 @@ static int generateOutputSubroutine( /* Suppress the first OFFSET entries if there is an OFFSET clause */ - codeOffset(v, p, iContinue); + codeOffset(v, p->iOffset, iContinue); switch( pDest->eDest ){ /* Store the result as data using a unique key. @@ -101672,7 +102529,7 @@ static int generateOutputSubroutine( /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); + sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); } /* Generate the subroutine return @@ -101780,9 +102637,7 @@ static int multiSelectOrderBy( SelectDest destA; /* Destination for coroutine A */ SelectDest destB; /* Destination for coroutine B */ int regAddrA; /* Address register for select-A coroutine */ - int regEofA; /* Flag to indicate when select-A is complete */ int regAddrB; /* Address register for select-B coroutine */ - int regEofB; /* Flag to indicate when select-B is complete */ int addrSelectA; /* Address of the select-A coroutine */ int addrSelectB; /* Address of the select-B coroutine */ int regOutA; /* Address register for the output-A subroutine */ @@ -101790,6 +102645,7 @@ static int multiSelectOrderBy( int addrOutA; /* Address of the output-A subroutine */ int addrOutB = 0; /* Address of the output-B subroutine */ int addrEofA; /* Address of the select-A-exhausted subroutine */ + int addrEofA_noB; /* Alternate addrEofA if B is uninitialized */ int addrEofB; /* Address of the select-B-exhausted subroutine */ int addrAltB; /* Address of the Au.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; } - pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1); - if( pKeyMerge ){ - for(i=0; ia[i].pExpr; - if( pTerm->flags & EP_Collate ){ - pColl = sqlite3ExprCollSeq(pParse, pTerm); - }else{ - pColl = multiSelectCollSeq(pParse, p, aPermute[i]); - if( pColl==0 ) pColl = db->pDfltColl; - pOrderBy->a[i].pExpr = - sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); - } - assert( sqlite3KeyInfoIsWriteable(pKeyMerge) ); - pKeyMerge->aColl[i] = pColl; - pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; - } - } + pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); }else{ pKeyMerge = 0; } @@ -101921,6 +102760,7 @@ static int multiSelectOrderBy( /* Separate the left and the right query from one another */ p->pPrior = 0; + pPrior->pNext = 0; sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); if( pPrior->pPrior==0 ){ sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); @@ -101943,37 +102783,30 @@ static int multiSelectOrderBy( p->pOffset = 0; regAddrA = ++pParse->nMem; - regEofA = ++pParse->nMem; regAddrB = ++pParse->nMem; - regEofB = ++pParse->nMem; regOutA = ++pParse->nMem; regOutB = ++pParse->nMem; sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); - /* Jump past the various subroutines and coroutines to the main - ** merge loop - */ - j1 = sqlite3VdbeAddOp0(v, OP_Goto); - addrSelectA = sqlite3VdbeCurrentAddr(v); - - /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. */ - VdbeNoopComment((v, "Begin coroutine for left SELECT")); + addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; + j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); + VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; explainSetInteger(iSub1, pParse->iNextSelectId); sqlite3Select(pParse, pPrior, &destA); - sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); - VdbeNoopComment((v, "End coroutine for left SELECT")); + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); + sqlite3VdbeJumpHere(v, j1); /* Generate a coroutine to evaluate the SELECT statement on ** the right - the "B" select */ - addrSelectB = sqlite3VdbeCurrentAddr(v); - VdbeNoopComment((v, "Begin coroutine for right SELECT")); + addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; + j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); + VdbeComment((v, "right SELECT")); savedLimit = p->iLimit; savedOffset = p->iOffset; p->iLimit = regLimitB; @@ -101982,9 +102815,7 @@ static int multiSelectOrderBy( sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; - sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); - VdbeNoopComment((v, "End coroutine for right SELECT")); + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB); /* Generate a subroutine that outputs the current row of the A ** select as the next output row of the compound select. @@ -102008,13 +102839,13 @@ static int multiSelectOrderBy( /* Generate a subroutine to run when the results from select A ** are exhausted and only data in select B remains. */ - VdbeNoopComment((v, "eof-A subroutine")); if( op==TK_EXCEPT || op==TK_INTERSECT ){ - addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd); + addrEofA_noB = addrEofA = labelEnd; }else{ - addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd); - sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); + VdbeNoopComment((v, "eof-A subroutine")); + addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); + addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); p->nSelectRow += pPrior->nSelectRow; } @@ -102027,9 +102858,8 @@ static int multiSelectOrderBy( if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; }else{ VdbeNoopComment((v, "eof-B subroutine")); - addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); - sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); + addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); } @@ -102037,8 +102867,7 @@ static int multiSelectOrderBy( */ VdbeNoopComment((v, "A-lt-B subroutine")); addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); - sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* Generate code to handle the case of A==B @@ -102051,8 +102880,7 @@ static int multiSelectOrderBy( }else{ VdbeNoopComment((v, "A-eq-B subroutine")); addrAeqB = - sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); - sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); } @@ -102063,19 +102891,14 @@ static int multiSelectOrderBy( if( op==TK_ALL || op==TK_UNION ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); } - sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); - sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB); - sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA); - sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB); - sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); - sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); /* Implement the main merge loop */ @@ -102084,7 +102907,7 @@ static int multiSelectOrderBy( sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO); sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); + sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); /* Jump to the this point in order to terminate the query. */ @@ -102104,6 +102927,7 @@ static int multiSelectOrderBy( sqlite3SelectDelete(db, p->pPrior); } p->pPrior = pPrior; + pPrior->pNext = p; /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ @@ -102309,6 +103133,14 @@ static void substSelect( ** (21) The subquery does not use LIMIT or the outer query is not ** DISTINCT. (See ticket [752e1646fc]). ** +** (22) The subquery is not a recursive CTE. +** +** (23) The parent is not a recursive CTE, or the sub-query is not a +** compound query. This restriction is because transforming the +** parent to a compound query confuses the code that handles +** recursive queries in multiSelect(). +** +** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. @@ -102361,7 +103193,7 @@ static int flattenSubquery( ** and (14). */ if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ if( pSub->pOffset ) return 0; /* Restriction (14) */ - if( p->pRightmost && pSub->pLimit ){ + if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){ return 0; /* Restriction (15) */ } if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ @@ -102380,6 +103212,8 @@ static int flattenSubquery( if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ return 0; /* Restriction (21) */ } + if( pSub->selFlags & SF_Recursive ) return 0; /* Restriction (22) */ + if( (p->selFlags & SF_Recursive) && pSub->pPrior ) return 0; /* (23) */ /* OBSOLETE COMMENT 1: ** Restriction 3: If the subquery is a join, make sure the subquery is @@ -102510,14 +103344,14 @@ static int flattenSubquery( p->pOrderBy = pOrderBy; p->pSrc = pSrc; p->op = TK_ALL; - p->pRightmost = 0; if( pNew==0 ){ - pNew = pPrior; + p->pPrior = pPrior; }else{ pNew->pPrior = pPrior; - pNew->pRightmost = 0; + if( pPrior ) pPrior->pNext = pNew; + pNew->pNext = p; + p->pPrior = pNew; } - p->pPrior = pNew; if( db->mallocFailed ) return 1; } @@ -102856,11 +103690,207 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ pNew->pHaving = 0; pNew->pOrderBy = 0; p->pPrior = 0; + p->pNext = 0; + p->selFlags &= ~SF_Compound; + assert( pNew->pPrior!=0 ); + pNew->pPrior->pNext = pNew; pNew->pLimit = 0; pNew->pOffset = 0; return WRC_Continue; } +#ifndef SQLITE_OMIT_CTE +/* +** Argument pWith (which may be NULL) points to a linked list of nested +** WITH contexts, from inner to outermost. If the table identified by +** FROM clause element pItem is really a common-table-expression (CTE) +** then return a pointer to the CTE definition for that table. Otherwise +** return NULL. +** +** If a non-NULL value is returned, set *ppContext to point to the With +** object that the returned CTE belongs to. +*/ +static struct Cte *searchWith( + With *pWith, /* Current outermost WITH clause */ + struct SrcList_item *pItem, /* FROM clause element to resolve */ + With **ppContext /* OUT: WITH clause return value belongs to */ +){ + const char *zName; + if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){ + With *p; + for(p=pWith; p; p=p->pOuter){ + int i; + for(i=0; inCte; i++){ + if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ + *ppContext = p; + return &p->a[i]; + } + } + } + } + return 0; +} + +/* The code generator maintains a stack of active WITH clauses +** with the inner-most WITH clause being at the top of the stack. +** +** This routine pushes the WITH clause passed as the second argument +** onto the top of the stack. If argument bFree is true, then this +** WITH clause will never be popped from the stack. In this case it +** should be freed along with the Parse object. In other cases, when +** bFree==0, the With object will be freed along with the SELECT +** statement with which it is associated. +*/ +SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ + assert( bFree==0 || pParse->pWith==0 ); + if( pWith ){ + pWith->pOuter = pParse->pWith; + pParse->pWith = pWith; + pParse->bFreeWith = bFree; + } +} + +/* +** This function checks if argument pFrom refers to a CTE declared by +** a WITH clause on the stack currently maintained by the parser. And, +** if currently processing a CTE expression, if it is a recursive +** reference to the current CTE. +** +** If pFrom falls into either of the two categories above, pFrom->pTab +** and other fields are populated accordingly. The caller should check +** (pFrom->pTab!=0) to determine whether or not a successful match +** was found. +** +** Whether or not a match is found, SQLITE_OK is returned if no error +** occurs. If an error does occur, an error message is stored in the +** parser and some error code other than SQLITE_OK returned. +*/ +static int withExpand( + Walker *pWalker, + struct SrcList_item *pFrom +){ + Parse *pParse = pWalker->pParse; + sqlite3 *db = pParse->db; + struct Cte *pCte; /* Matched CTE (or NULL if no match) */ + With *pWith; /* WITH clause that pCte belongs to */ + + assert( pFrom->pTab==0 ); + + pCte = searchWith(pParse->pWith, pFrom, &pWith); + if( pCte ){ + Table *pTab; + ExprList *pEList; + Select *pSel; + Select *pLeft; /* Left-most SELECT statement */ + int bMayRecursive; /* True if compound joined by UNION [ALL] */ + With *pSavedWith; /* Initial value of pParse->pWith */ + + /* If pCte->zErr is non-NULL at this point, then this is an illegal + ** recursive reference to CTE pCte. Leave an error in pParse and return + ** early. If pCte->zErr is NULL, then this is not a recursive reference. + ** In this case, proceed. */ + if( pCte->zErr ){ + sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName); + return SQLITE_ERROR; + } + + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTab==0 ) return WRC_Abort; + pTab->nRef = 1; + pTab->zName = sqlite3DbStrDup(db, pCte->zName); + pTab->iPKey = -1; + pTab->nRowEst = 1048576; + pTab->tabFlags |= TF_Ephemeral; + pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); + if( db->mallocFailed ) return SQLITE_NOMEM; + assert( pFrom->pSelect ); + + /* Check if this is a recursive CTE. */ + pSel = pFrom->pSelect; + bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION ); + if( bMayRecursive ){ + int i; + SrcList *pSrc = pFrom->pSelect->pSrc; + for(i=0; inSrc; i++){ + struct SrcList_item *pItem = &pSrc->a[i]; + if( pItem->zDatabase==0 + && pItem->zName!=0 + && 0==sqlite3StrICmp(pItem->zName, pCte->zName) + ){ + pItem->pTab = pTab; + pItem->isRecursive = 1; + pTab->nRef++; + pSel->selFlags |= SF_Recursive; + } + } + } + + /* Only one recursive reference is permitted. */ + if( pTab->nRef>2 ){ + sqlite3ErrorMsg( + pParse, "multiple references to recursive table: %s", pCte->zName + ); + return SQLITE_ERROR; + } + assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); + + pCte->zErr = "circular reference: %s"; + pSavedWith = pParse->pWith; + pParse->pWith = pWith; + sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); + + for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); + pEList = pLeft->pEList; + if( pCte->pCols ){ + if( pEList->nExpr!=pCte->pCols->nExpr ){ + sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", + pCte->zName, pEList->nExpr, pCte->pCols->nExpr + ); + pParse->pWith = pSavedWith; + return SQLITE_ERROR; + } + pEList = pCte->pCols; + } + + selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); + if( bMayRecursive ){ + if( pSel->selFlags & SF_Recursive ){ + pCte->zErr = "multiple recursive references: %s"; + }else{ + pCte->zErr = "recursive reference in a subquery: %s"; + } + sqlite3WalkSelect(pWalker, pSel); + } + pCte->zErr = 0; + pParse->pWith = pSavedWith; + } + + return SQLITE_OK; +} +#endif + +#ifndef SQLITE_OMIT_CTE +/* +** If the SELECT passed as the second argument has an associated WITH +** clause, pop it from the stack stored as part of the Parse object. +** +** This function is used as the xSelectCallback2() callback by +** sqlite3SelectExpand() when walking a SELECT tree to resolve table +** names and other FROM clause elements. +*/ +static void selectPopWith(Walker *pWalker, Select *p){ + Parse *pParse = pWalker->pParse; + With *pWith = findRightmost(p)->pWith; + if( pWith!=0 ){ + assert( pParse->pWith==pWith ); + pParse->pWith = pWith->pOuter; + } +} +#else +#define selectPopWith 0 +#endif + /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: @@ -102904,6 +103934,7 @@ static int selectExpander(Walker *pWalker, Select *p){ } pTabList = p->pSrc; pEList = p->pEList; + sqlite3WithPush(pParse, findRightmost(p)->pWith, 0); /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. @@ -102916,12 +103947,21 @@ static int selectExpander(Walker *pWalker, Select *p){ */ for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab; + assert( pFrom->isRecursive==0 || pFrom->pTab ); + if( pFrom->isRecursive ) continue; if( pFrom->pTab!=0 ){ /* This statement has already been prepared. There is no need ** to go further. */ assert( i==0 ); +#ifndef SQLITE_OMIT_CTE + selectPopWith(pWalker, p); +#endif return WRC_Prune; } +#ifndef SQLITE_OMIT_CTE + if( withExpand(pWalker, pFrom) ) return WRC_Abort; + if( pFrom->pTab ) {} else +#endif if( pFrom->zName==0 ){ #ifndef SQLITE_OMIT_SUBQUERY Select *pSel = pFrom->pSelect; @@ -103184,6 +104224,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; + w.xSelectCallback2 = selectPopWith; sqlite3WalkSelect(&w, pSelect); } @@ -103202,7 +104243,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ ** at that point because identifiers had not yet been resolved. This ** routine is called after identifier resolution. */ -static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ +static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Parse *pParse; int i; SrcList *pTabList; @@ -103218,13 +104259,13 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ /* A sub-query in the FROM clause of a SELECT */ Select *pSel = pFrom->pSelect; - assert( pSel ); - while( pSel->pPrior ) pSel = pSel->pPrior; - selectAddColumnTypeAndCollation(pParse, pTab, pSel); + if( pSel ){ + while( pSel->pPrior ) pSel = pSel->pPrior; + selectAddColumnTypeAndCollation(pParse, pTab, pSel); + } } } } - return WRC_Continue; } #endif @@ -103240,10 +104281,9 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; memset(&w, 0, sizeof(w)); - w.xSelectCallback = selectAddSubqueryTypeInfo; + w.xSelectCallback2 = selectAddSubqueryTypeInfo; w.xExprCallback = exprWalkNoop; w.pParse = pParse; - w.bSelectDepthFirst = 1; sqlite3WalkSelect(&w, pSelect); #endif } @@ -103290,14 +104330,23 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; - if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ - return; - } + int nReg = pAggInfo->nFunc + pAggInfo->nColumn; + if( nReg==0 ) return; +#ifdef SQLITE_DEBUG + /* Verify that all AggInfo registers are within the range specified by + ** AggInfo.mnReg..AggInfo.mxReg */ + assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 ); for(i=0; inColumn; i++){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem); + assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg + && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg ); } + for(i=0; inFunc; i++){ + assert( pAggInfo->aFunc[i].iMem>=pAggInfo->mnReg + && pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg ); + } +#endif + sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg); for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem); if( pFunc->iDistinct>=0 ){ Expr *pE = pFunc->pExpr; assert( !ExprHasProperty(pE, EP_xIsSelect) ); @@ -103306,7 +104355,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ "argument"); pFunc->iDistinct = -1; }else{ - KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList); + KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0); sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO); } @@ -103343,7 +104392,6 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ struct AggInfo_col *pC; pAggInfo->directMode = 1; - sqlite3ExprCacheClear(pParse); for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ int nArg; int addrNext = 0; @@ -103399,7 +104447,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ ** values to an OP_Copy. */ if( regHit ){ - addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); + addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); } sqlite3ExprCacheClear(pParse); for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ @@ -103440,50 +104488,8 @@ static void explainSimpleCount( /* ** Generate code for the SELECT statement given in the p argument. ** -** The results are distributed in various ways depending on the -** contents of the SelectDest structure pointed to by argument pDest -** as follows: -** -** pDest->eDest Result -** ------------ ------------------------------------------- -** SRT_Output Generate a row of output (using the OP_ResultRow -** opcode) for each row in the result set. -** -** SRT_Mem Only valid if the result is a single column. -** Store the first column of the first result row -** in register pDest->iSDParm then abandon the rest -** of the query. This destination implies "LIMIT 1". -** -** SRT_Set The result must be a single column. Store each -** row of result as the key in table pDest->iSDParm. -** Apply the affinity pDest->affSdst before storing -** results. Used to implement "IN (SELECT ...)". -** -** SRT_Union Store results as a key in a temporary table -** identified by pDest->iSDParm. -** -** SRT_Except Remove results from the temporary table pDest->iSDParm. -** -** SRT_Table Store results in temporary table pDest->iSDParm. -** This is like SRT_EphemTab except that the table -** is assumed to already be open. -** -** SRT_EphemTab Create an temporary table pDest->iSDParm and store -** the result there. The cursor is left open after -** returning. This is like SRT_Table except that -** this destination uses OP_OpenEphemeral to create -** the table first. -** -** SRT_Coroutine Generate a co-routine that returns a new row of -** results each time it is invoked. The entry point -** of the co-routine is stored in register pDest->iSDParm. -** -** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result -** set is not empty. -** -** SRT_Discard Throw the results away. This is used by SELECT -** statements within triggers whose only purpose is -** the side-effects of functions. +** The results are returned according to the SelectDest structure. +** See comments in sqliteInt.h for further information. ** ** This routine returns the number of errors. If any errors are ** encountered, then an appropriate error message is left in @@ -103600,42 +104606,24 @@ SQLITE_PRIVATE int sqlite3Select( p->selFlags |= SF_Aggregate; } i = -1; - }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0 - && OptimizationEnabled(db, SQLITE_SubqCoroutine) + }else if( pTabList->nSrc==1 + && OptimizationEnabled(db, SQLITE_SubqCoroutine) ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. */ - int addrTop; - int addrEof; + int addrTop = sqlite3VdbeCurrentAddr(v)+1; pItem->regReturn = ++pParse->nMem; - addrEof = ++pParse->nMem; - /* Before coding the OP_Goto to jump to the start of the main routine, - ** ensure that the jump to the verify-schema routine has already - ** been coded. Otherwise, the verify-schema would likely be coded as - ** part of the co-routine. If the main routine then accessed the - ** database before invoking the co-routine for the first time (for - ** example to initialize a LIMIT register from a sub-select), it would - ** be doing so without having verified the schema version and obtained - ** the required db locks. See ticket d6b36be38. */ - sqlite3CodeVerifySchema(pParse, -1); - sqlite3VdbeAddOp0(v, OP_Goto); - addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor); - sqlite3VdbeChangeP5(v, 1); - VdbeComment((v, "coroutine for %s", pItem->pTab->zName)); + sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); + VdbeComment((v, "%s", pItem->pTab->zName)); pItem->addrFillSub = addrTop; - sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof); - sqlite3VdbeChangeP5(v, 1); sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; pItem->viaCoroutine = 1; - sqlite3VdbeChangeP2(v, addrTop, dest.iSdst); - sqlite3VdbeChangeP3(v, addrTop, dest.nSdst); - sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof); - sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn); - VdbeComment((v, "end %s", pItem->pTab->zName)); + pItem->regResult = dest.iSdst; + sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); sqlite3VdbeJumpHere(v, addrTop-1); sqlite3ClearTempRegCache(pParse); }else{ @@ -103651,12 +104639,14 @@ SQLITE_PRIVATE int sqlite3Select( pItem->regReturn = ++pParse->nMem; topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); pItem->addrFillSub = topAddr+1; - VdbeNoopComment((v, "materialize %s", pItem->pTab->zName)); if( pItem->isCorrelated==0 ){ /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ - onceAddr = sqlite3CodeOnce(pParse); + onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); + VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); + }else{ + VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); } sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); @@ -103688,21 +104678,6 @@ SQLITE_PRIVATE int sqlite3Select( /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ - if( p->pRightmost==0 ){ - Select *pLoop, *pRight = 0; - int cnt = 0; - int mxSelect; - for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){ - pLoop->pRightmost = p; - pLoop->pNext = pRight; - pRight = pLoop; - } - mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; - if( mxSelect && cnt>mxSelect ){ - sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); - goto select_end; - } - } rc = multiSelect(pParse, p, pDest); explainSetInteger(pParse->iSelectId, iRestoreSelectId); return rc; @@ -103758,7 +104733,7 @@ SQLITE_PRIVATE int sqlite3Select( */ if( pOrderBy ){ KeyInfo *pKeyInfo; - pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); + pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 0); pOrderBy->iECursor = pParse->nTab++; p->addrOpenEphm[2] = addrSortIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, @@ -103790,7 +104765,7 @@ SQLITE_PRIVATE int sqlite3Select( sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sDistinct.tabTnct, 0, 0, - (char*)keyInfoFromExprList(pParse, p->pEList), + (char*)keyInfoFromExprList(pParse, p->pEList, 0), P4_KEYINFO); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; @@ -103824,7 +104799,7 @@ SQLITE_PRIVATE int sqlite3Select( } /* Use the standard inner loop. */ - selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest, + selectInnerLoop(pParse, p, pEList, -1, pOrderBy, &sDistinct, pDest, sqlite3WhereContinueLabel(pWInfo), sqlite3WhereBreakLabel(pWInfo)); @@ -103876,6 +104851,7 @@ SQLITE_PRIVATE int sqlite3Select( sNC.pParse = pParse; sNC.pSrcList = pTabList; sNC.pAggInfo = &sAggInfo; + sAggInfo.mnReg = pParse->nMem+1; sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; sAggInfo.pGroupBy = pGroupBy; sqlite3ExprAnalyzeAggList(&sNC, pEList); @@ -103890,6 +104866,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList); sNC.ncFlags &= ~NC_InAggFunc; } + sAggInfo.mxReg = pParse->nMem; if( db->mallocFailed ) goto select_end; /* Processing for aggregates with GROUP BY is very different and @@ -103912,7 +104889,7 @@ SQLITE_PRIVATE int sqlite3Select( ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse->nTab++; - pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0); addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 0, (char*)pKeyInfo, P4_KEYINFO); @@ -104004,7 +104981,7 @@ SQLITE_PRIVATE int sqlite3Select( sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); - VdbeComment((v, "GROUP BY sort")); + VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); sAggInfo.useSortingIdx = 1; sqlite3ExprCacheClear(pParse); } @@ -104031,7 +105008,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); j1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); + sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v); /* Generate code that runs whenever the GROUP BY changes. ** Changes in the GROUP BY are detected by the previous code @@ -104045,7 +105022,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); VdbeComment((v, "output one row")); - sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); + sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v); VdbeComment((v, "check abort flag")); sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); VdbeComment((v, "reset accumulator")); @@ -104062,6 +105039,7 @@ SQLITE_PRIVATE int sqlite3Select( */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); + VdbeCoverage(v); }else{ sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); @@ -104089,12 +105067,12 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); sqlite3VdbeResolveLabel(v, addrOutputRow); addrOutputRow = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); + sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, + selectInnerLoop(pParse, p, p->pEList, -1, pOrderBy, &sDistinct, pDest, addrOutputRow+1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); @@ -104237,7 +105215,7 @@ SQLITE_PRIVATE int sqlite3Select( pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0, + selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, pDest, addrEnd, addrEnd); sqlite3ExprListDelete(db, pDel); } @@ -104362,10 +105340,6 @@ SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ sqlite3ExplainPrintf(pVdbe, "(null-select)"); return; } - while( p->pPrior ){ - p->pPrior->pNext = p; - p = p->pPrior; - } sqlite3ExplainPush(pVdbe); while( p ){ explainOneSelect(pVdbe, p); @@ -104981,25 +105955,21 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( sqlite3 *db, /* The database connection */ Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ - ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ Select *pSelect, /* A SELECT statement that supplies values */ u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ){ TriggerStep *pTriggerStep; - assert(pEList == 0 || pSelect == 0); - assert(pEList != 0 || pSelect != 0 || db->mallocFailed); + assert(pSelect != 0 || db->mallocFailed); pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); if( pTriggerStep ){ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; - pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->orconf = orconf; }else{ sqlite3IdListDelete(db, pColumn); } - sqlite3ExprListDelete(db, pEList); sqlite3SelectDelete(db, pSelect); return pTriggerStep; @@ -105154,6 +106124,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ int base; + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList dropTrigger[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String8, 0, 1, 0}, /* 1 */ @@ -105168,7 +106139,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); - base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); + base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger, iLn); sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT); sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); sqlite3ChangeCookie(pParse, iDb); @@ -105314,15 +106285,7 @@ static int codeTriggerProgram( ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; - - /* Clear the cookieGoto flag. When coding triggers, the cookieGoto - ** variable is used as a flag to indicate to sqlite3ExprCodeConstants() - ** that it is not safe to refactor constants (this happens after the - ** start of the first loop in the SQL statement is coded - at that - ** point code may be conditionally executed, so it is no longer safe to - ** initialize constant register values). */ - assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 ); - pParse->cookieGoto = 0; + assert( pParse->okConstFactor==0 ); switch( pStep->op ){ case TK_UPDATE: { @@ -105337,7 +106300,6 @@ static int codeTriggerProgram( case TK_INSERT: { sqlite3Insert(pParse, targetSrcList(pParse, pStep), - sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3IdListDup(db, pStep->pIdList), pParse->eOrconf @@ -105794,7 +106756,7 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); } #ifndef SQLITE_OMIT_FLOATING_POINT - if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ + if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); } #endif @@ -106112,7 +107074,7 @@ SQLITE_PRIVATE void sqlite3Update( regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, - sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); } sqlite3WhereEnd(pWInfo); @@ -106156,18 +107118,23 @@ SQLITE_PRIVATE void sqlite3Update( if( aToOpen[iDataCur-iBaseCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); + VdbeCoverageNeverTaken(v); } labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); + VdbeCoverage(v); }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); + VdbeCoverage(v); }else{ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, regOldRowid); + VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); } /* If the record number will change, set register regNewRowid to @@ -106177,7 +107144,7 @@ SQLITE_PRIVATE void sqlite3Update( assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); if( chngRowid ){ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); } /* Compute the old pre-UPDATE content of the row being changed, if that @@ -106189,9 +107156,10 @@ SQLITE_PRIVATE void sqlite3Update( ); for(i=0; inCol; i++){ if( oldmask==0xffffffff - || (i<32 && (oldmask & (1<aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){ + testcase( oldmask!=0xffffffff && i==31 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i); @@ -106218,15 +107186,15 @@ SQLITE_PRIVATE void sqlite3Update( newmask = sqlite3TriggerColmask( pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError ); - sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1); + /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/ for(i=0; inCol; i++){ if( i==pTab->iPKey ){ - /*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/ + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); }else{ j = aXRef[i]; if( j>=0 ){ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); - }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<31 || (newmask & MASKBIT32(i)) ){ /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or ** if there are one or more BEFORE triggers that use this value via @@ -106235,6 +107203,8 @@ SQLITE_PRIVATE void sqlite3Update( testcase( i==31 ); testcase( i==32 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } } } @@ -106243,8 +107213,7 @@ SQLITE_PRIVATE void sqlite3Update( ** verified. One could argue that this is wrong. */ if( tmask&TRIGGER_BEFORE ){ - sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); - sqlite3TableAffinityStr(v, pTab); + sqlite3TableAffinity(v, pTab, regNew); sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); @@ -106256,8 +107225,10 @@ SQLITE_PRIVATE void sqlite3Update( */ if( pPk ){ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); + VdbeCoverage(v); }else{ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); } /* If it did not delete it, the row-trigger may still have modified @@ -106293,6 +107264,7 @@ SQLITE_PRIVATE void sqlite3Update( }else{ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); } + VdbeCoverageNeverTaken(v); } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); @@ -106336,7 +107308,7 @@ SQLITE_PRIVATE void sqlite3Update( /* Nothing to do at end-of-loop for a single-pass */ }else if( pPk ){ sqlite3VdbeResolveLabel(v, labelContinue); - sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); + sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue); } @@ -106465,7 +107437,7 @@ static void updateVirtualTable( /* Generate code to scan the ephemeral table and call VUpdate. */ iReg = ++pParse->nMem; pParse->nMem += pTab->nCol+1; - addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); + addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); for(i=0; inCol; i++){ @@ -106475,7 +107447,7 @@ static void updateVirtualTable( sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); @@ -108047,7 +109019,7 @@ struct WhereLevel { int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ u8 iFrom; /* Which entry in the FROM clause */ - u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */ + u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on pWLoop->wsFlags */ struct { @@ -108434,6 +109406,7 @@ struct WhereInfo { #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ +#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in where.c **********************/ @@ -109086,7 +110059,7 @@ static int isLikeOrGlob( } assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ - pRight = pList->a[0].pExpr; + pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); op = pRight->op; if( op==TK_VARIABLE ){ Vdbe *pReprepare = pParse->pReprepare; @@ -110020,7 +110993,7 @@ static void constructAutomaticIndex( ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); - addrInit = sqlite3CodeOnce(pParse); + addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ @@ -110127,12 +111100,12 @@ static void constructAutomaticIndex( VdbeComment((v, "for %s", pTable->zName)); /* Fill the automatic index with content */ - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); regRecord = sqlite3GetTempReg(pParse); - sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0); + sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0); sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeJumpHere(v, addrTop); sqlite3ReleaseTempReg(pParse, regRecord); @@ -110170,7 +111143,8 @@ static sqlite3_index_info *allocateIndexInfo( assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); - if( pTerm->eOperator & (WO_ISNULL) ) continue; + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; nTerm++; } @@ -110222,7 +111196,8 @@ static sqlite3_index_info *allocateIndexInfo( assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); - if( pTerm->eOperator & (WO_ISNULL) ) continue; + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; @@ -110330,7 +111305,7 @@ static void whereKeyStats( assert( pRec->nField>0 && iColnSampleCol ); do{ iTest = (iMin+i)/2; - res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec); + res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0); if( res<0 ){ iMin = iTest+1; }else{ @@ -110345,16 +111320,16 @@ static void whereKeyStats( if( res==0 ){ /* If (res==0) is true, then sample $i must be equal to pRec */ assert( inSample ); - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0) || pParse->db->mallocFailed ); }else{ /* Otherwise, pRec must be smaller than sample $i and larger than ** sample ($i-1). */ assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 + || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0 || pParse->db->mallocFailed ); assert( i==0 - || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 + || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0 || pParse->db->mallocFailed ); } #endif /* ifdef SQLITE_DEBUG */ @@ -110806,6 +111781,8 @@ static int codeEqualityTerm( } iTab = pX->iTable; sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); + VdbeCoverageIf(v, bRev); + VdbeCoverageIf(v, !bRev); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); pLoop->wsFlags |= WHERE_IN_ABLE; if( pLevel->u.in.nIn==0 ){ @@ -110825,7 +111802,7 @@ static int codeEqualityTerm( pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); } pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; - sqlite3VdbeAddOp1(v, OP_IsNull, iReg); + sqlite3VdbeAddOp1(v, OP_IsNull, iReg); VdbeCoverage(v); }else{ pLevel->u.in.nIn = 0; } @@ -110920,10 +111897,14 @@ static int codeAllEqualityTerms( if( nSkip ){ int iIdxCur = pLevel->iIdxCur; sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); j = sqlite3VdbeAddOp0(v, OP_Goto); - pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLt:OP_SeekGt), + pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), iIdxCur, 0, regBase, nSkip); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); sqlite3VdbeJumpHere(v, j); for(j=0; jeOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ Expr *pRight = pTerm->pExpr->pRight; - sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk); + if( sqlite3ExprCanBeNull(pRight) ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); + VdbeCoverage(v); + } if( zAff ){ if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){ zAff[j] = SQLITE_AFF_NONE; @@ -110987,7 +111971,7 @@ static void explainAppendTerm( const char *zOp /* Name of the operator */ ){ if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); - sqlite3StrAccumAppend(pStr, zColumn, -1); + sqlite3StrAccumAppendAll(pStr, zColumn); sqlite3StrAccumAppend(pStr, zOp, 1); sqlite3StrAccumAppend(pStr, "?", 1); } @@ -111033,7 +112017,7 @@ static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){ }else{ if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5); sqlite3StrAccumAppend(&txt, "ANY(", 4); - sqlite3StrAccumAppend(&txt, z, -1); + sqlite3StrAccumAppendAll(&txt, z); sqlite3StrAccumAppend(&txt, ")", 1); } } @@ -111202,10 +112186,10 @@ static Bitmask codeOneLoopStart( /* Special case of a FROM clause subquery implemented as a co-routine */ if( pTabItem->viaCoroutine ){ int regYield = pTabItem->regReturn; - sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield); - pLevel->p2 = sqlite3VdbeAddOp1(v, OP_Yield, regYield); - VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName)); - sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk); + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); + VdbeCoverage(v); + VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); pLevel->op = OP_Goto; }else @@ -111237,6 +112221,7 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); + VdbeCoverage(v); pLoop->u.vtab.needFree = 0; for(j=0; ju.vtab.omitMask>>j)&1 ){ @@ -111260,16 +112245,18 @@ static Bitmask codeOneLoopStart( ** construct. */ assert( pLoop->u.btree.nEq==1 ); - iReleaseReg = sqlite3GetTempReg(pParse); pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); + iReleaseReg = ++pParse->nMem; iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); + if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); + sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); + VdbeCoverage(v); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); VdbeComment((v, "pk")); @@ -111303,10 +112290,10 @@ static Bitmask codeOneLoopStart( ** seek opcodes. It depends on a particular ordering of TK_xx */ const u8 aMoveOp[] = { - /* TK_GT */ OP_SeekGt, - /* TK_LE */ OP_SeekLe, - /* TK_LT */ OP_SeekLt, - /* TK_GE */ OP_SeekGe + /* TK_GT */ OP_SeekGT, + /* TK_LE */ OP_SeekLE, + /* TK_LT */ OP_SeekLT, + /* TK_GE */ OP_SeekGE }; assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ @@ -111320,11 +112307,17 @@ static Bitmask codeOneLoopStart( r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); VdbeComment((v, "pk")); + VdbeCoverageIf(v, pX->op==TK_GT); + VdbeCoverageIf(v, pX->op==TK_LE); + VdbeCoverageIf(v, pX->op==TK_LT); + VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); } if( pEnd ){ Expr *pX; @@ -111348,10 +112341,14 @@ static Bitmask codeOneLoopStart( pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); + VdbeCoverageIf(v, testOp==OP_Le); + VdbeCoverageIf(v, testOp==OP_Lt); + VdbeCoverageIf(v, testOp==OP_Ge); + VdbeCoverageIf(v, testOp==OP_Gt); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ @@ -111391,20 +112388,19 @@ static Bitmask codeOneLoopStart( 0, OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ OP_Last, /* 3: (!start_constraints && startEq && bRev) */ - OP_SeekGt, /* 4: (start_constraints && !startEq && !bRev) */ - OP_SeekLt, /* 5: (start_constraints && !startEq && bRev) */ - OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */ - OP_SeekLe /* 7: (start_constraints && startEq && bRev) */ + OP_SeekGT, /* 4: (start_constraints && !startEq && !bRev) */ + OP_SeekLT, /* 5: (start_constraints && !startEq && bRev) */ + OP_SeekGE, /* 6: (start_constraints && startEq && !bRev) */ + OP_SeekLE /* 7: (start_constraints && startEq && bRev) */ }; static const u8 aEndOp[] = { - OP_Noop, /* 0: (!end_constraints) */ - OP_IdxGE, /* 1: (end_constraints && !bRev) */ - OP_IdxLT /* 2: (end_constraints && bRev) */ + OP_IdxGE, /* 0: (end_constraints && !bRev && !endEq) */ + OP_IdxGT, /* 1: (end_constraints && !bRev && endEq) */ + OP_IdxLE, /* 2: (end_constraints && bRev && !endEq) */ + OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */ }; u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ - int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ int regBase; /* Base register holding constraint values */ - int r1; /* Temp register */ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ int startEq; /* True if range start uses ==, >= or <= */ @@ -111417,6 +112413,8 @@ static Bitmask codeOneLoopStart( int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ char cEndAff = 0; /* Affinity for end of range constraint */ + u8 bSeekPastNull = 0; /* True to seek past initial nulls */ + u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; @@ -111435,7 +112433,7 @@ static Bitmask codeOneLoopStart( && (pIdx->nKeyCol>nEq) ){ assert( pLoop->u.btree.nSkip==0 ); - isMinQuery = 1; + bSeekPastNull = 1; nExtraReg = 1; } @@ -111450,7 +112448,14 @@ static Bitmask codeOneLoopStart( if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; + if( pRangeStart==0 + && (j = pIdx->aiColumn[nEq])>=0 + && pIdx->pTable->aCol[j].notNull==0 + ){ + bSeekPastNull = 1; + } } + assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers @@ -111469,6 +112474,7 @@ static Bitmask codeOneLoopStart( || (bRev && pIdx->nKeyCol==nEq) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); + SWAP(u8, bSeekPastNull, bStopAtNull); } testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); @@ -111484,8 +112490,11 @@ static Bitmask codeOneLoopStart( if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; sqlite3ExprCode(pParse, pRight, regBase+nEq); - if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){ - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); + if( (pRangeStart->wtFlags & TERM_VNULL)==0 + && sqlite3ExprCanBeNull(pRight) + ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); + VdbeCoverage(v); } if( zStartAff ){ if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){ @@ -111500,22 +112509,23 @@ static Bitmask codeOneLoopStart( } nConstraint++; testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); - }else if( isMinQuery ){ + }else if( bSeekPastNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); nConstraint++; startEq = 0; start_constraints = 1; } - codeApplyAffinity(pParse, regBase, nConstraint, zStartAff); + codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); - testcase( op==OP_Rewind ); - testcase( op==OP_Last ); - testcase( op==OP_SeekGt ); - testcase( op==OP_SeekGe ); - testcase( op==OP_SeekLe ); - testcase( op==OP_SeekLt ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); + VdbeCoverage(v); + VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); + VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); + VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); + VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); + VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); + VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); /* Load the value for the inequality constraint at the end of the ** range (if any). @@ -111525,8 +112535,11 @@ static Bitmask codeOneLoopStart( Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); sqlite3ExprCode(pParse, pRight, regBase+nEq); - if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){ - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); + if( (pRangeEnd->wtFlags & TERM_VNULL)==0 + && sqlite3ExprCanBeNull(pRight) + ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); + VdbeCoverage(v); } if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff) @@ -111535,6 +112548,10 @@ static Bitmask codeOneLoopStart( } nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); + }else if( bStopAtNull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + endEq = 0; + nConstraint++; } sqlite3DbFree(db, zStartAff); @@ -111542,40 +112559,22 @@ static Bitmask codeOneLoopStart( pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ - op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)]; - testcase( op==OP_Noop ); - testcase( op==OP_IdxGE ); - testcase( op==OP_IdxLT ); - if( op!=OP_Noop ){ + if( nConstraint ){ + op = aEndOp[bRev*2 + endEq]; sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0); + testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); + testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); + testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); + testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } - /* If there are inequality constraints, check that the value - ** of the table column that the inequality contrains is not NULL. - ** If it is, jump to the next iteration of the loop. - */ - r1 = sqlite3GetTempReg(pParse); - testcase( pLoop->wsFlags & WHERE_BTM_LIMIT ); - testcase( pLoop->wsFlags & WHERE_TOP_LIMIT ); - if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 - && (j = pIdx->aiColumn[nEq])>=0 - && pIdx->pTable->aCol[j].notNull==0 - && (nEq || (pLoop->wsFlags & WHERE_BTM_LIMIT)==0) - ){ - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); - VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName)); - sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont); - } - sqlite3ReleaseTempReg(pParse, r1); - /* Seek the table cursor, if required */ disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ @@ -111587,7 +112586,7 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); } sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, - iRowidReg, pPk->nKeyCol); + iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } /* Record the instruction used to terminate the loop. Disable @@ -111601,6 +112600,8 @@ static Bitmask codeOneLoopStart( pLevel->op = OP_Next; } pLevel->p1 = iIdxCur; + assert( (WHERE_UNQ_WANTED>>16)==1 ); + pLevel->p3 = (pLoop->wsFlags>>16)&1; if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){ pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; }else{ @@ -111731,7 +112732,9 @@ static Bitmask codeOneLoopStart( Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; - if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue; + testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); + if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); @@ -111767,6 +112770,7 @@ static Bitmask codeOneLoopStart( regRowid, 0); sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, sqlite3VdbeCurrentAddr(v)+2, r, iSet); + VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); @@ -111827,10 +112831,18 @@ static Bitmask codeOneLoopStart( static const u8 aStep[] = { OP_Next, OP_Prev }; static const u8 aStart[] = { OP_Rewind, OP_Last }; assert( bRev==0 || bRev==1 ); - pLevel->op = aStep[bRev]; - pLevel->p1 = iCur; - pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); - pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; + if( pTabItem->isRecursive ){ + /* Tables marked isRecursive have only a single row that is stored in + ** a pseudo-cursor. No need to Rewind or Next such cursors. */ + pLevel->op = OP_Noop; + }else{ + pLevel->op = aStep[bRev]; + pLevel->p1 = iCur; + pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); + pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; + } } /* Insert code to test every subexpression that can be completely @@ -111910,7 +112922,6 @@ static Bitmask codeOneLoopStart( pTerm->wtFlags |= TERM_CODED; } } - sqlite3ReleaseTempReg(pParse, iReleaseReg); return pLevel->notReady; } @@ -112347,6 +113358,7 @@ static int whereLoopAddBtreeIndex( && saved_nEq==saved_nSkip && saved_nEq+1nKeyCol && pProbe->aiRowEst[saved_nEq+1]>=18 /* TUNING: Minimum for skip-scan */ + && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK ){ LogEst nIter; pNew->u.btree.nEq++; @@ -112354,7 +113366,10 @@ static int whereLoopAddBtreeIndex( pNew->aLTerm[pNew->nLTerm++] = 0; pNew->wsFlags |= WHERE_SKIPSCAN; nIter = sqlite3LogEst(pProbe->aiRowEst[0]/pProbe->aiRowEst[saved_nEq+1]); + pNew->rRun = rLogSize + nIter; + pNew->nOut += nIter; whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter); + pNew->nOut = saved_nOut; } for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; @@ -112396,12 +113411,13 @@ static int whereLoopAddBtreeIndex( || nInMul==0 ); pNew->wsFlags |= WHERE_COLUMN_EQ; - if( iCol<0 - || (pProbe->onError!=OE_None && nInMul==0 - && pNew->u.btree.nEq==pProbe->nKeyCol-1) - ){ + if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1)){ assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 ); - pNew->wsFlags |= WHERE_ONEROW; + if( iCol>=0 && pProbe->onError==OE_None ){ + pNew->wsFlags |= WHERE_UNQ_WANTED; + }else{ + pNew->wsFlags |= WHERE_ONEROW; + } } pNew->u.btree.nEq++; pNew->nOut = nRowEst + nInMul; @@ -112614,6 +113630,7 @@ static int whereLoopAddBtree( && !pSrc->notIndexed && HasRowid(pTab) && !pSrc->isCorrelated + && !pSrc->isRecursive ){ /* Generate auto-index WhereLoops */ WhereTerm *pTerm; @@ -113279,9 +114296,12 @@ static int wherePathSatisfiesOrderBy( orderDistinctMask |= pLoop->maskSelf; for(i=0; ia[i].pExpr; - if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){ + mTerm = exprTableUsage(&pWInfo->sMaskSet,p); + if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; + if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } @@ -113843,14 +114863,16 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( initMaskSet(pMaskSet); whereClauseInit(&pWInfo->sWC, pWInfo); whereSplit(&pWInfo->sWC, pWhere, TK_AND); - sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ - if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ - sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); - pWhere = 0; + for(ii=0; iinTerm; ii++){ + if( nTabList==0 || sqlite3ExprIsConstantNotJoin(sWLB.pWC->a[ii].pExpr) ){ + sqlite3ExprIfFalse(pParse, sWLB.pWC->a[ii].pExpr, pWInfo->iBreak, + SQLITE_JUMPIFNULL); + sWLB.pWC->a[ii].wtFlags |= TERM_CODED; + } } /* Special case: No FROM clause @@ -113902,22 +114924,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( goto whereBeginError; } - /* If the ORDER BY (or GROUP BY) clause contains references to general - ** expressions, then we won't be able to satisfy it using indices, so - ** go ahead and disable it now. - */ - if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ){ - pWInfo->pOrderBy = pOrderBy = 0; - break; - }else if( pExpr->iColumn<0 ){ - break; - } - } - } - if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ @@ -114129,7 +115135,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( sqlite3VdbeSetP4KeyInfo(pParse, pIx); VdbeComment((v, "%s", pIx->zName)); } - sqlite3CodeVerifySchema(pParse, iDb); + if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor); } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); @@ -114191,8 +115197,12 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ pLoop = pLevel->pWLoop; sqlite3VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ - sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); + sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeChangeP5(v, pLevel->p5); + VdbeCoverage(v); + VdbeCoverageIf(v, pLevel->op==OP_Next); + VdbeCoverageIf(v, pLevel->op==OP_Prev); + VdbeCoverageIf(v, pLevel->op==OP_VNext); } if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; @@ -114201,6 +115211,9 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } sqlite3DbFree(db, pLevel->u.in.aInLoop); @@ -114213,7 +115226,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); } if( pLevel->iLeftJoin ){ - addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); + addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ @@ -114240,12 +115253,38 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ assert( pWInfo->nLevel<=pTabList->nSrc ); for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ + int k, last; + VdbeOp *pOp; Index *pIdx = 0; struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; Table *pTab = pTabItem->pTab; assert( pTab!=0 ); pLoop = pLevel->pWLoop; + /* For a co-routine, change all OP_Column references to the table of + ** the co-routine into OP_SCopy of result contained in a register. + ** OP_Rowid becomes OP_Null. + */ + if( pTabItem->viaCoroutine && !db->mallocFailed ){ + last = sqlite3VdbeCurrentAddr(v); + k = pLevel->addrBody; + pOp = sqlite3VdbeGetOp(v, k); + for(; kp1!=pLevel->iTabCur ) continue; + if( pOp->opcode==OP_Column ){ + pOp->opcode = OP_SCopy; + pOp->p1 = pOp->p2 + pTabItem->regResult; + pOp->p2 = pOp->p3; + pOp->p3 = 0; + }else if( pOp->opcode==OP_Rowid ){ + pOp->opcode = OP_Null; + pOp->p1 = 0; + pOp->p3 = 0; + } + } + continue; + } + /* Close all of the cursors that were opened by sqlite3WhereBegin. ** Except, do not close cursors that will be reused by the OR optimization ** (WHERE_OMIT_OPEN_CLOSE). And do not close the OP_OpenWrite cursors @@ -114284,9 +115323,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ pIdx = pLevel->u.pCovidx; } if( pIdx && !db->mallocFailed ){ - int k, last; - VdbeOp *pOp; - last = sqlite3VdbeCurrentAddr(v); k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); @@ -114381,14 +115417,6 @@ struct TrigEvent { int a; IdList * b; }; */ struct AttachKey { int type; Token key; }; -/* -** One or more VALUES claues -*/ -struct ValueList { - ExprList *pList; - Select *pSelect; -}; - /* This is a utility routine used to set the ExprSpan.zStart and ** ExprSpan.zEnd values of pOut so that the span covers the complete @@ -114512,28 +115540,28 @@ struct ValueList { ** defined, then do no error processing. */ #define YYCODETYPE unsigned char -#define YYNOCODE 253 +#define YYNOCODE 254 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 68 +#define YYWILDCARD 70 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - int yy4; - struct TrigEvent yy90; - ExprSpan yy118; - u16 yy177; - TriggerStep* yy203; - u8 yy210; - struct {int value; int mask;} yy215; - SrcList* yy259; - struct ValueList yy260; - struct LimitVal yy292; - Expr* yy314; - ExprList* yy322; - struct LikeOp yy342; - IdList* yy384; - Select* yy387; + Select* yy3; + ExprList* yy14; + With* yy59; + SrcList* yy65; + struct LikeOp yy96; + Expr* yy132; + u8 yy186; + int yy328; + ExprSpan yy346; + struct TrigEvent yy378; + u16 yy381; + IdList* yy408; + struct {int value; int mask;} yy429; + TriggerStep* yy473; + struct LimitVal yy476; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -114542,8 +115570,8 @@ typedef union { #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 631 -#define YYNRULE 329 +#define YYNSTATE 642 +#define YYNRULE 327 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) @@ -114613,480 +115641,463 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ -#define YY_ACTTAB_COUNT (1582) +#define YY_ACTTAB_COUNT (1497) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 312, 961, 185, 420, 2, 171, 516, 515, 597, 56, - /* 10 */ 56, 56, 56, 49, 54, 54, 54, 54, 53, 53, - /* 20 */ 52, 52, 52, 51, 234, 197, 196, 195, 624, 623, - /* 30 */ 301, 590, 584, 56, 56, 56, 56, 156, 54, 54, - /* 40 */ 54, 54, 53, 53, 52, 52, 52, 51, 234, 628, - /* 50 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 60 */ 56, 56, 56, 466, 54, 54, 54, 54, 53, 53, - /* 70 */ 52, 52, 52, 51, 234, 312, 597, 52, 52, 52, - /* 80 */ 51, 234, 33, 54, 54, 54, 54, 53, 53, 52, - /* 90 */ 52, 52, 51, 234, 624, 623, 621, 620, 165, 624, - /* 100 */ 623, 383, 380, 379, 214, 328, 590, 584, 624, 623, - /* 110 */ 467, 59, 378, 619, 618, 617, 53, 53, 52, 52, - /* 120 */ 52, 51, 234, 506, 507, 57, 58, 48, 582, 581, - /* 130 */ 583, 583, 55, 55, 56, 56, 56, 56, 30, 54, - /* 140 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 150 */ 312, 50, 47, 146, 233, 232, 207, 474, 256, 349, - /* 160 */ 255, 475, 621, 620, 554, 438, 298, 621, 620, 236, - /* 170 */ 674, 435, 440, 553, 439, 366, 621, 620, 540, 224, - /* 180 */ 551, 590, 584, 176, 138, 282, 386, 277, 385, 168, - /* 190 */ 600, 422, 951, 548, 622, 951, 273, 572, 572, 566, - /* 200 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 210 */ 56, 56, 56, 354, 54, 54, 54, 54, 53, 53, - /* 220 */ 52, 52, 52, 51, 234, 312, 561, 526, 62, 675, - /* 230 */ 132, 595, 410, 348, 579, 579, 492, 426, 577, 419, - /* 240 */ 627, 65, 329, 560, 441, 237, 676, 123, 607, 67, - /* 250 */ 542, 532, 622, 170, 205, 500, 590, 584, 166, 559, - /* 260 */ 622, 403, 593, 593, 593, 442, 443, 271, 422, 950, - /* 270 */ 166, 223, 950, 483, 190, 57, 58, 48, 582, 581, - /* 280 */ 583, 583, 55, 55, 56, 56, 56, 56, 600, 54, - /* 290 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 300 */ 312, 441, 412, 376, 175, 165, 166, 391, 383, 380, - /* 310 */ 379, 342, 412, 203, 426, 66, 392, 622, 415, 378, - /* 320 */ 597, 166, 442, 338, 444, 571, 601, 74, 415, 624, - /* 330 */ 623, 590, 584, 624, 623, 174, 601, 92, 333, 171, - /* 340 */ 1, 410, 597, 579, 579, 624, 623, 600, 306, 425, - /* 350 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 360 */ 56, 56, 56, 580, 54, 54, 54, 54, 53, 53, - /* 370 */ 52, 52, 52, 51, 234, 312, 472, 262, 399, 68, - /* 380 */ 412, 339, 571, 389, 624, 623, 578, 602, 597, 589, - /* 390 */ 588, 603, 412, 622, 423, 533, 415, 621, 620, 513, - /* 400 */ 257, 621, 620, 166, 601, 91, 590, 584, 415, 45, - /* 410 */ 597, 586, 585, 621, 620, 250, 601, 92, 39, 347, - /* 420 */ 576, 336, 597, 547, 567, 57, 58, 48, 582, 581, - /* 430 */ 583, 583, 55, 55, 56, 56, 56, 56, 587, 54, - /* 440 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 450 */ 312, 561, 621, 620, 531, 291, 470, 188, 399, 375, - /* 460 */ 247, 492, 249, 350, 412, 476, 476, 368, 560, 299, - /* 470 */ 334, 412, 281, 482, 67, 565, 410, 622, 579, 579, - /* 480 */ 415, 590, 584, 280, 559, 467, 520, 415, 601, 92, - /* 490 */ 597, 167, 544, 36, 877, 601, 16, 519, 564, 6, - /* 500 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 510 */ 56, 56, 56, 200, 54, 54, 54, 54, 53, 53, - /* 520 */ 52, 52, 52, 51, 234, 312, 183, 412, 236, 528, - /* 530 */ 395, 535, 358, 256, 349, 255, 397, 412, 248, 182, - /* 540 */ 353, 359, 549, 415, 236, 317, 563, 50, 47, 146, - /* 550 */ 273, 601, 73, 415, 7, 311, 590, 584, 568, 493, - /* 560 */ 213, 601, 92, 233, 232, 410, 173, 579, 579, 330, - /* 570 */ 575, 574, 631, 629, 332, 57, 58, 48, 582, 581, - /* 580 */ 583, 583, 55, 55, 56, 56, 56, 56, 199, 54, - /* 590 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 600 */ 312, 492, 340, 320, 511, 505, 572, 572, 460, 562, - /* 610 */ 549, 170, 145, 430, 67, 558, 410, 622, 579, 579, - /* 620 */ 384, 236, 600, 412, 408, 575, 574, 504, 572, 572, - /* 630 */ 571, 590, 584, 353, 198, 143, 268, 549, 316, 415, - /* 640 */ 306, 424, 207, 50, 47, 146, 167, 601, 69, 546, - /* 650 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 660 */ 56, 56, 56, 555, 54, 54, 54, 54, 53, 53, - /* 670 */ 52, 52, 52, 51, 234, 312, 600, 326, 412, 270, - /* 680 */ 145, 264, 274, 266, 459, 571, 423, 35, 412, 568, - /* 690 */ 407, 213, 428, 388, 415, 308, 212, 143, 622, 354, - /* 700 */ 317, 12, 601, 94, 415, 549, 590, 584, 50, 47, - /* 710 */ 146, 365, 601, 97, 552, 362, 318, 147, 602, 361, - /* 720 */ 325, 15, 603, 187, 206, 57, 58, 48, 582, 581, - /* 730 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54, - /* 740 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 750 */ 312, 412, 35, 412, 415, 22, 630, 2, 600, 50, - /* 760 */ 47, 146, 601, 95, 412, 485, 510, 415, 412, 415, - /* 770 */ 412, 11, 235, 486, 412, 601, 104, 601, 103, 19, - /* 780 */ 415, 590, 584, 352, 415, 40, 415, 38, 601, 105, - /* 790 */ 415, 32, 601, 106, 601, 133, 544, 169, 601, 134, - /* 800 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 810 */ 56, 56, 56, 412, 54, 54, 54, 54, 53, 53, - /* 820 */ 52, 52, 52, 51, 234, 312, 412, 274, 412, 415, - /* 830 */ 412, 274, 274, 274, 201, 230, 721, 601, 98, 484, - /* 840 */ 427, 307, 415, 622, 415, 540, 415, 622, 622, 622, - /* 850 */ 601, 102, 601, 101, 601, 93, 590, 584, 262, 21, - /* 860 */ 129, 622, 522, 521, 554, 222, 469, 521, 600, 324, - /* 870 */ 323, 322, 211, 553, 622, 57, 58, 48, 582, 581, - /* 880 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54, - /* 890 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 900 */ 312, 412, 261, 412, 415, 412, 600, 210, 625, 367, - /* 910 */ 51, 234, 601, 100, 538, 606, 142, 415, 355, 415, - /* 920 */ 412, 415, 412, 496, 622, 601, 77, 601, 96, 601, - /* 930 */ 137, 590, 584, 530, 622, 529, 415, 141, 415, 28, - /* 940 */ 524, 600, 229, 544, 601, 136, 601, 135, 604, 204, - /* 950 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 960 */ 56, 56, 56, 412, 54, 54, 54, 54, 53, 53, - /* 970 */ 52, 52, 52, 51, 234, 312, 412, 360, 412, 415, - /* 980 */ 412, 360, 286, 600, 503, 220, 127, 601, 76, 629, - /* 990 */ 332, 382, 415, 622, 415, 540, 415, 622, 412, 613, - /* 1000 */ 601, 90, 601, 89, 601, 75, 590, 584, 341, 272, - /* 1010 */ 377, 622, 126, 27, 415, 622, 164, 544, 125, 280, - /* 1020 */ 373, 122, 601, 88, 480, 57, 46, 48, 582, 581, - /* 1030 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54, - /* 1040 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 1050 */ 312, 412, 360, 412, 415, 412, 284, 186, 369, 321, - /* 1060 */ 477, 170, 601, 87, 121, 473, 221, 415, 622, 415, - /* 1070 */ 254, 415, 412, 355, 412, 601, 99, 601, 86, 601, - /* 1080 */ 17, 590, 584, 259, 612, 120, 159, 158, 415, 622, - /* 1090 */ 415, 14, 465, 157, 462, 25, 601, 85, 601, 84, - /* 1100 */ 622, 58, 48, 582, 581, 583, 583, 55, 55, 56, - /* 1110 */ 56, 56, 56, 412, 54, 54, 54, 54, 53, 53, - /* 1120 */ 52, 52, 52, 51, 234, 312, 412, 262, 412, 415, - /* 1130 */ 412, 262, 118, 611, 117, 24, 10, 601, 83, 351, - /* 1140 */ 216, 219, 415, 622, 415, 608, 415, 622, 412, 622, - /* 1150 */ 601, 72, 601, 71, 601, 82, 590, 584, 262, 4, - /* 1160 */ 605, 622, 458, 115, 415, 456, 252, 154, 452, 110, - /* 1170 */ 108, 453, 601, 81, 622, 451, 622, 48, 582, 581, - /* 1180 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54, - /* 1190 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234, - /* 1200 */ 44, 406, 450, 3, 415, 412, 262, 107, 416, 623, - /* 1210 */ 446, 437, 601, 80, 436, 335, 238, 189, 411, 409, - /* 1220 */ 594, 415, 622, 44, 406, 401, 3, 412, 557, 601, - /* 1230 */ 70, 416, 623, 412, 622, 149, 622, 421, 404, 64, - /* 1240 */ 412, 622, 409, 415, 622, 331, 139, 148, 566, 415, - /* 1250 */ 449, 601, 18, 228, 124, 626, 415, 601, 79, 315, - /* 1260 */ 181, 404, 412, 545, 601, 78, 262, 541, 41, 42, - /* 1270 */ 534, 566, 390, 202, 262, 43, 414, 413, 415, 622, - /* 1280 */ 595, 314, 622, 622, 180, 539, 601, 92, 415, 276, - /* 1290 */ 622, 41, 42, 509, 616, 615, 601, 9, 43, 414, - /* 1300 */ 413, 622, 418, 595, 262, 622, 275, 600, 614, 622, - /* 1310 */ 218, 593, 593, 593, 592, 591, 13, 178, 217, 417, - /* 1320 */ 622, 236, 622, 44, 406, 490, 3, 269, 399, 267, - /* 1330 */ 609, 416, 623, 400, 593, 593, 593, 592, 591, 13, - /* 1340 */ 265, 622, 409, 622, 263, 622, 34, 406, 244, 3, - /* 1350 */ 258, 363, 464, 463, 416, 623, 622, 356, 251, 8, - /* 1360 */ 622, 404, 177, 599, 455, 409, 622, 622, 622, 622, - /* 1370 */ 445, 566, 243, 622, 622, 236, 295, 240, 31, 239, - /* 1380 */ 622, 431, 30, 396, 404, 290, 622, 294, 622, 293, - /* 1390 */ 144, 41, 42, 622, 566, 622, 394, 622, 43, 414, - /* 1400 */ 413, 622, 289, 595, 398, 60, 622, 292, 37, 231, - /* 1410 */ 598, 172, 622, 29, 41, 42, 393, 523, 622, 556, - /* 1420 */ 184, 43, 414, 413, 287, 387, 595, 543, 285, 518, - /* 1430 */ 537, 536, 517, 327, 593, 593, 593, 592, 591, 13, - /* 1440 */ 215, 283, 278, 514, 513, 304, 303, 302, 179, 300, - /* 1450 */ 512, 310, 454, 128, 227, 226, 309, 593, 593, 593, - /* 1460 */ 592, 591, 13, 494, 489, 225, 488, 150, 487, 242, - /* 1470 */ 163, 61, 374, 481, 162, 161, 624, 623, 241, 372, - /* 1480 */ 209, 479, 370, 260, 26, 160, 478, 364, 468, 471, - /* 1490 */ 140, 152, 119, 467, 131, 116, 155, 153, 345, 457, - /* 1500 */ 151, 346, 130, 114, 113, 112, 111, 448, 319, 23, - /* 1510 */ 109, 434, 20, 433, 432, 429, 566, 610, 573, 596, - /* 1520 */ 63, 405, 191, 279, 510, 296, 498, 288, 570, 495, - /* 1530 */ 499, 497, 461, 194, 5, 305, 193, 192, 381, 569, - /* 1540 */ 357, 256, 344, 245, 526, 246, 253, 313, 595, 343, - /* 1550 */ 447, 297, 236, 402, 550, 491, 508, 502, 501, 527, - /* 1560 */ 234, 208, 525, 962, 962, 962, 371, 962, 962, 962, - /* 1570 */ 962, 962, 962, 962, 962, 337, 962, 962, 962, 593, - /* 1580 */ 593, 593, + /* 0 */ 306, 212, 432, 955, 639, 191, 955, 295, 559, 88, + /* 10 */ 88, 88, 88, 81, 86, 86, 86, 86, 85, 85, + /* 20 */ 84, 84, 84, 83, 330, 185, 184, 183, 635, 635, + /* 30 */ 292, 606, 606, 88, 88, 88, 88, 683, 86, 86, + /* 40 */ 86, 86, 85, 85, 84, 84, 84, 83, 330, 16, + /* 50 */ 436, 597, 89, 90, 80, 600, 599, 601, 601, 87, + /* 60 */ 87, 88, 88, 88, 88, 684, 86, 86, 86, 86, + /* 70 */ 85, 85, 84, 84, 84, 83, 330, 306, 559, 84, + /* 80 */ 84, 84, 83, 330, 65, 86, 86, 86, 86, 85, + /* 90 */ 85, 84, 84, 84, 83, 330, 635, 635, 634, 633, + /* 100 */ 182, 682, 550, 379, 376, 375, 17, 322, 606, 606, + /* 110 */ 371, 198, 479, 91, 374, 82, 79, 165, 85, 85, + /* 120 */ 84, 84, 84, 83, 330, 598, 635, 635, 107, 89, + /* 130 */ 90, 80, 600, 599, 601, 601, 87, 87, 88, 88, + /* 140 */ 88, 88, 186, 86, 86, 86, 86, 85, 85, 84, + /* 150 */ 84, 84, 83, 330, 306, 594, 594, 142, 328, 327, + /* 160 */ 484, 249, 344, 238, 635, 635, 634, 633, 585, 448, + /* 170 */ 526, 525, 229, 388, 1, 394, 450, 584, 449, 635, + /* 180 */ 635, 635, 635, 319, 395, 606, 606, 199, 157, 273, + /* 190 */ 382, 268, 381, 187, 635, 635, 634, 633, 311, 555, + /* 200 */ 266, 593, 593, 266, 347, 588, 89, 90, 80, 600, + /* 210 */ 599, 601, 601, 87, 87, 88, 88, 88, 88, 478, + /* 220 */ 86, 86, 86, 86, 85, 85, 84, 84, 84, 83, + /* 230 */ 330, 306, 272, 536, 634, 633, 146, 610, 197, 310, + /* 240 */ 575, 182, 482, 271, 379, 376, 375, 506, 21, 634, + /* 250 */ 633, 634, 633, 635, 635, 374, 611, 574, 548, 440, + /* 260 */ 111, 563, 606, 606, 634, 633, 324, 479, 608, 608, + /* 270 */ 608, 300, 435, 573, 119, 407, 210, 162, 562, 883, + /* 280 */ 592, 592, 306, 89, 90, 80, 600, 599, 601, 601, + /* 290 */ 87, 87, 88, 88, 88, 88, 506, 86, 86, 86, + /* 300 */ 86, 85, 85, 84, 84, 84, 83, 330, 620, 111, + /* 310 */ 635, 635, 361, 606, 606, 358, 249, 349, 248, 433, + /* 320 */ 243, 479, 586, 634, 633, 195, 611, 93, 119, 221, + /* 330 */ 575, 497, 534, 534, 89, 90, 80, 600, 599, 601, + /* 340 */ 601, 87, 87, 88, 88, 88, 88, 574, 86, 86, + /* 350 */ 86, 86, 85, 85, 84, 84, 84, 83, 330, 306, + /* 360 */ 77, 429, 638, 573, 589, 530, 240, 230, 242, 105, + /* 370 */ 249, 349, 248, 515, 588, 208, 460, 529, 564, 173, + /* 380 */ 634, 633, 970, 144, 430, 2, 424, 228, 380, 557, + /* 390 */ 606, 606, 190, 153, 159, 158, 514, 51, 632, 631, + /* 400 */ 630, 71, 536, 432, 954, 196, 610, 954, 614, 45, + /* 410 */ 18, 89, 90, 80, 600, 599, 601, 601, 87, 87, + /* 420 */ 88, 88, 88, 88, 261, 86, 86, 86, 86, 85, + /* 430 */ 85, 84, 84, 84, 83, 330, 306, 608, 608, 608, + /* 440 */ 542, 424, 402, 385, 241, 506, 451, 320, 211, 543, + /* 450 */ 164, 436, 386, 293, 451, 587, 108, 496, 111, 334, + /* 460 */ 391, 591, 424, 614, 27, 452, 453, 606, 606, 72, + /* 470 */ 257, 70, 259, 452, 339, 342, 564, 582, 68, 415, + /* 480 */ 469, 328, 327, 62, 614, 45, 110, 393, 89, 90, + /* 490 */ 80, 600, 599, 601, 601, 87, 87, 88, 88, 88, + /* 500 */ 88, 152, 86, 86, 86, 86, 85, 85, 84, 84, + /* 510 */ 84, 83, 330, 306, 110, 499, 520, 538, 402, 389, + /* 520 */ 424, 110, 566, 500, 593, 593, 454, 82, 79, 165, + /* 530 */ 424, 591, 384, 564, 340, 615, 188, 162, 424, 350, + /* 540 */ 616, 424, 614, 44, 606, 606, 445, 582, 300, 434, + /* 550 */ 151, 19, 614, 9, 568, 580, 348, 615, 469, 567, + /* 560 */ 614, 26, 616, 614, 45, 89, 90, 80, 600, 599, + /* 570 */ 601, 601, 87, 87, 88, 88, 88, 88, 411, 86, + /* 580 */ 86, 86, 86, 85, 85, 84, 84, 84, 83, 330, + /* 590 */ 306, 579, 110, 578, 521, 282, 433, 398, 400, 255, + /* 600 */ 486, 82, 79, 165, 487, 164, 82, 79, 165, 488, + /* 610 */ 488, 364, 387, 424, 544, 544, 509, 350, 362, 155, + /* 620 */ 191, 606, 606, 559, 642, 640, 333, 82, 79, 165, + /* 630 */ 305, 564, 507, 312, 357, 614, 45, 329, 596, 595, + /* 640 */ 194, 337, 89, 90, 80, 600, 599, 601, 601, 87, + /* 650 */ 87, 88, 88, 88, 88, 424, 86, 86, 86, 86, + /* 660 */ 85, 85, 84, 84, 84, 83, 330, 306, 20, 323, + /* 670 */ 150, 263, 211, 543, 421, 596, 595, 614, 22, 424, + /* 680 */ 193, 424, 284, 424, 391, 424, 509, 424, 577, 424, + /* 690 */ 186, 335, 424, 559, 424, 313, 120, 546, 606, 606, + /* 700 */ 67, 614, 47, 614, 50, 614, 48, 614, 100, 614, + /* 710 */ 99, 614, 101, 576, 614, 102, 614, 109, 326, 89, + /* 720 */ 90, 80, 600, 599, 601, 601, 87, 87, 88, 88, + /* 730 */ 88, 88, 424, 86, 86, 86, 86, 85, 85, 84, + /* 740 */ 84, 84, 83, 330, 306, 424, 311, 424, 585, 54, + /* 750 */ 424, 516, 517, 590, 614, 112, 424, 584, 424, 572, + /* 760 */ 424, 195, 424, 571, 424, 67, 424, 614, 94, 614, + /* 770 */ 98, 424, 614, 97, 264, 606, 606, 195, 614, 46, + /* 780 */ 614, 96, 614, 30, 614, 49, 614, 115, 614, 114, + /* 790 */ 418, 229, 388, 614, 113, 306, 89, 90, 80, 600, + /* 800 */ 599, 601, 601, 87, 87, 88, 88, 88, 88, 424, + /* 810 */ 86, 86, 86, 86, 85, 85, 84, 84, 84, 83, + /* 820 */ 330, 119, 424, 590, 110, 372, 606, 606, 195, 53, + /* 830 */ 250, 614, 29, 195, 472, 438, 729, 190, 302, 498, + /* 840 */ 14, 523, 641, 2, 614, 43, 306, 89, 90, 80, + /* 850 */ 600, 599, 601, 601, 87, 87, 88, 88, 88, 88, + /* 860 */ 424, 86, 86, 86, 86, 85, 85, 84, 84, 84, + /* 870 */ 83, 330, 424, 613, 964, 964, 354, 606, 606, 420, + /* 880 */ 312, 64, 614, 42, 391, 355, 283, 437, 301, 255, + /* 890 */ 414, 410, 495, 492, 614, 28, 471, 306, 89, 90, + /* 900 */ 80, 600, 599, 601, 601, 87, 87, 88, 88, 88, + /* 910 */ 88, 424, 86, 86, 86, 86, 85, 85, 84, 84, + /* 920 */ 84, 83, 330, 424, 110, 110, 110, 110, 606, 606, + /* 930 */ 110, 254, 13, 614, 41, 532, 531, 283, 481, 531, + /* 940 */ 457, 284, 119, 561, 356, 614, 40, 284, 306, 89, + /* 950 */ 78, 80, 600, 599, 601, 601, 87, 87, 88, 88, + /* 960 */ 88, 88, 424, 86, 86, 86, 86, 85, 85, 84, + /* 970 */ 84, 84, 83, 330, 110, 424, 341, 220, 555, 606, + /* 980 */ 606, 351, 555, 318, 614, 95, 413, 255, 83, 330, + /* 990 */ 284, 284, 255, 640, 333, 356, 255, 614, 39, 306, + /* 1000 */ 356, 90, 80, 600, 599, 601, 601, 87, 87, 88, + /* 1010 */ 88, 88, 88, 424, 86, 86, 86, 86, 85, 85, + /* 1020 */ 84, 84, 84, 83, 330, 424, 317, 316, 141, 465, + /* 1030 */ 606, 606, 219, 619, 463, 614, 10, 417, 462, 255, + /* 1040 */ 189, 510, 553, 351, 207, 363, 161, 614, 38, 315, + /* 1050 */ 218, 255, 255, 80, 600, 599, 601, 601, 87, 87, + /* 1060 */ 88, 88, 88, 88, 424, 86, 86, 86, 86, 85, + /* 1070 */ 85, 84, 84, 84, 83, 330, 76, 419, 255, 3, + /* 1080 */ 878, 461, 424, 247, 331, 331, 614, 37, 217, 76, + /* 1090 */ 419, 390, 3, 216, 215, 422, 4, 331, 331, 424, + /* 1100 */ 547, 12, 424, 545, 614, 36, 424, 541, 422, 424, + /* 1110 */ 540, 424, 214, 424, 408, 424, 539, 403, 605, 605, + /* 1120 */ 237, 614, 25, 119, 614, 24, 588, 408, 614, 45, + /* 1130 */ 118, 614, 35, 614, 34, 614, 33, 614, 23, 588, + /* 1140 */ 60, 223, 603, 602, 513, 378, 73, 74, 140, 139, + /* 1150 */ 424, 110, 265, 75, 426, 425, 59, 424, 610, 73, + /* 1160 */ 74, 549, 402, 404, 424, 373, 75, 426, 425, 604, + /* 1170 */ 138, 610, 614, 11, 392, 76, 419, 181, 3, 614, + /* 1180 */ 32, 271, 369, 331, 331, 493, 614, 31, 149, 608, + /* 1190 */ 608, 608, 607, 15, 422, 365, 614, 8, 137, 489, + /* 1200 */ 136, 190, 608, 608, 608, 607, 15, 485, 176, 135, + /* 1210 */ 7, 252, 477, 408, 174, 133, 175, 474, 57, 56, + /* 1220 */ 132, 130, 119, 76, 419, 588, 3, 468, 245, 464, + /* 1230 */ 171, 331, 331, 125, 123, 456, 447, 122, 446, 104, + /* 1240 */ 336, 231, 422, 166, 154, 73, 74, 332, 116, 431, + /* 1250 */ 121, 309, 75, 426, 425, 222, 106, 610, 308, 637, + /* 1260 */ 204, 408, 629, 627, 628, 6, 200, 428, 427, 290, + /* 1270 */ 203, 622, 201, 588, 62, 63, 289, 66, 419, 399, + /* 1280 */ 3, 401, 288, 92, 143, 331, 331, 287, 608, 608, + /* 1290 */ 608, 607, 15, 73, 74, 227, 422, 325, 69, 416, + /* 1300 */ 75, 426, 425, 612, 412, 610, 192, 61, 569, 209, + /* 1310 */ 396, 226, 278, 225, 383, 408, 527, 558, 276, 533, + /* 1320 */ 552, 528, 321, 523, 370, 508, 180, 588, 494, 179, + /* 1330 */ 366, 117, 253, 269, 522, 503, 608, 608, 608, 607, + /* 1340 */ 15, 551, 502, 58, 274, 524, 178, 73, 74, 304, + /* 1350 */ 501, 368, 303, 206, 75, 426, 425, 491, 360, 610, + /* 1360 */ 213, 177, 483, 131, 345, 298, 297, 296, 202, 294, + /* 1370 */ 480, 490, 466, 134, 172, 129, 444, 346, 470, 128, + /* 1380 */ 314, 459, 103, 127, 126, 148, 124, 167, 443, 235, + /* 1390 */ 608, 608, 608, 607, 15, 442, 439, 623, 234, 299, + /* 1400 */ 145, 583, 291, 377, 581, 160, 119, 156, 270, 636, + /* 1410 */ 971, 169, 279, 626, 520, 625, 473, 624, 170, 621, + /* 1420 */ 618, 119, 168, 55, 409, 423, 537, 609, 286, 285, + /* 1430 */ 405, 570, 560, 556, 5, 52, 458, 554, 147, 267, + /* 1440 */ 519, 504, 518, 406, 262, 239, 260, 512, 343, 511, + /* 1450 */ 258, 353, 565, 256, 224, 251, 359, 277, 275, 476, + /* 1460 */ 475, 246, 352, 244, 467, 455, 236, 233, 232, 307, + /* 1470 */ 441, 281, 205, 163, 397, 280, 535, 505, 330, 617, + /* 1480 */ 971, 971, 971, 971, 367, 971, 971, 971, 971, 971, + /* 1490 */ 971, 971, 971, 971, 971, 971, 338, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 19, 143, 144, 145, 146, 24, 7, 8, 27, 78, - /* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - /* 20 */ 89, 90, 91, 92, 93, 106, 107, 108, 27, 28, - /* 30 */ 15, 50, 51, 78, 79, 80, 81, 26, 83, 84, - /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 1, - /* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 60 */ 79, 80, 81, 11, 83, 84, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 93, 19, 95, 89, 90, 91, - /* 80 */ 92, 93, 26, 83, 84, 85, 86, 87, 88, 89, - /* 90 */ 90, 91, 92, 93, 27, 28, 95, 96, 97, 27, - /* 100 */ 28, 100, 101, 102, 22, 19, 50, 51, 27, 28, - /* 110 */ 58, 55, 111, 7, 8, 9, 87, 88, 89, 90, - /* 120 */ 91, 92, 93, 98, 99, 69, 70, 71, 72, 73, - /* 130 */ 74, 75, 76, 77, 78, 79, 80, 81, 127, 83, - /* 140 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 150 */ 19, 223, 224, 225, 87, 88, 162, 31, 106, 107, - /* 160 */ 108, 35, 95, 96, 33, 98, 23, 95, 96, 117, - /* 170 */ 119, 243, 105, 42, 107, 49, 95, 96, 151, 93, - /* 180 */ 26, 50, 51, 97, 98, 99, 100, 101, 102, 103, - /* 190 */ 196, 22, 23, 121, 167, 26, 110, 130, 131, 67, - /* 200 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 210 */ 79, 80, 81, 219, 83, 84, 85, 86, 87, 88, - /* 220 */ 89, 90, 91, 92, 93, 19, 12, 95, 234, 119, - /* 230 */ 24, 99, 113, 239, 115, 116, 151, 68, 23, 147, - /* 240 */ 148, 26, 215, 29, 151, 153, 119, 155, 163, 164, - /* 250 */ 23, 23, 167, 26, 162, 23, 50, 51, 26, 45, - /* 260 */ 167, 47, 130, 131, 132, 172, 173, 23, 22, 23, - /* 270 */ 26, 186, 26, 188, 120, 69, 70, 71, 72, 73, - /* 280 */ 74, 75, 76, 77, 78, 79, 80, 81, 196, 83, - /* 290 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 300 */ 19, 151, 151, 23, 119, 97, 26, 19, 100, 101, - /* 310 */ 102, 219, 151, 162, 68, 22, 28, 167, 167, 111, - /* 320 */ 27, 26, 172, 173, 231, 232, 175, 176, 167, 27, - /* 330 */ 28, 50, 51, 27, 28, 119, 175, 176, 246, 24, - /* 340 */ 22, 113, 27, 115, 116, 27, 28, 196, 22, 23, - /* 350 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 360 */ 79, 80, 81, 114, 83, 84, 85, 86, 87, 88, - /* 370 */ 89, 90, 91, 92, 93, 19, 21, 151, 217, 22, - /* 380 */ 151, 231, 232, 222, 27, 28, 23, 114, 95, 50, - /* 390 */ 51, 118, 151, 167, 68, 89, 167, 95, 96, 104, - /* 400 */ 23, 95, 96, 26, 175, 176, 50, 51, 167, 22, - /* 410 */ 95, 72, 73, 95, 96, 16, 175, 176, 137, 64, - /* 420 */ 23, 195, 27, 121, 23, 69, 70, 71, 72, 73, - /* 430 */ 74, 75, 76, 77, 78, 79, 80, 81, 99, 83, - /* 440 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 450 */ 19, 12, 95, 96, 23, 226, 101, 22, 217, 19, - /* 460 */ 61, 151, 63, 222, 151, 106, 107, 108, 29, 159, - /* 470 */ 244, 151, 99, 163, 164, 23, 113, 167, 115, 116, - /* 480 */ 167, 50, 51, 110, 45, 58, 47, 167, 175, 176, - /* 490 */ 95, 51, 168, 137, 139, 175, 176, 58, 11, 22, - /* 500 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 510 */ 79, 80, 81, 22, 83, 84, 85, 86, 87, 88, - /* 520 */ 89, 90, 91, 92, 93, 19, 23, 151, 117, 23, - /* 530 */ 217, 207, 19, 106, 107, 108, 216, 151, 139, 23, - /* 540 */ 129, 28, 26, 167, 117, 105, 23, 223, 224, 225, - /* 550 */ 110, 175, 176, 167, 77, 165, 50, 51, 168, 169, - /* 560 */ 170, 175, 176, 87, 88, 113, 26, 115, 116, 171, - /* 570 */ 172, 173, 0, 1, 2, 69, 70, 71, 72, 73, - /* 580 */ 74, 75, 76, 77, 78, 79, 80, 81, 162, 83, - /* 590 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 600 */ 19, 151, 98, 217, 23, 37, 130, 131, 23, 23, - /* 610 */ 26, 26, 96, 163, 164, 23, 113, 167, 115, 116, - /* 620 */ 52, 117, 196, 151, 171, 172, 173, 59, 130, 131, - /* 630 */ 232, 50, 51, 129, 208, 209, 16, 121, 156, 167, - /* 640 */ 22, 23, 162, 223, 224, 225, 51, 175, 176, 121, - /* 650 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 660 */ 79, 80, 81, 178, 83, 84, 85, 86, 87, 88, - /* 670 */ 89, 90, 91, 92, 93, 19, 196, 109, 151, 23, - /* 680 */ 96, 61, 151, 63, 23, 232, 68, 26, 151, 168, - /* 690 */ 169, 170, 23, 89, 167, 26, 208, 209, 167, 219, - /* 700 */ 105, 36, 175, 176, 167, 121, 50, 51, 223, 224, - /* 710 */ 225, 229, 175, 176, 178, 233, 247, 248, 114, 239, - /* 720 */ 189, 22, 118, 24, 162, 69, 70, 71, 72, 73, - /* 730 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83, - /* 740 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 750 */ 19, 151, 26, 151, 167, 24, 145, 146, 196, 223, - /* 760 */ 224, 225, 175, 176, 151, 182, 183, 167, 151, 167, - /* 770 */ 151, 36, 199, 190, 151, 175, 176, 175, 176, 206, - /* 780 */ 167, 50, 51, 221, 167, 136, 167, 138, 175, 176, - /* 790 */ 167, 26, 175, 176, 175, 176, 168, 36, 175, 176, - /* 800 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 810 */ 79, 80, 81, 151, 83, 84, 85, 86, 87, 88, - /* 820 */ 89, 90, 91, 92, 93, 19, 151, 151, 151, 167, - /* 830 */ 151, 151, 151, 151, 162, 207, 23, 175, 176, 26, - /* 840 */ 249, 250, 167, 167, 167, 151, 167, 167, 167, 167, - /* 850 */ 175, 176, 175, 176, 175, 176, 50, 51, 151, 53, - /* 860 */ 22, 167, 192, 193, 33, 189, 192, 193, 196, 189, - /* 870 */ 189, 189, 162, 42, 167, 69, 70, 71, 72, 73, - /* 880 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83, - /* 890 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 900 */ 19, 151, 195, 151, 167, 151, 196, 162, 151, 215, - /* 910 */ 92, 93, 175, 176, 28, 174, 119, 167, 151, 167, - /* 920 */ 151, 167, 151, 182, 167, 175, 176, 175, 176, 175, - /* 930 */ 176, 50, 51, 23, 167, 23, 167, 40, 167, 22, - /* 940 */ 167, 196, 53, 168, 175, 176, 175, 176, 175, 162, - /* 950 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 960 */ 79, 80, 81, 151, 83, 84, 85, 86, 87, 88, - /* 970 */ 89, 90, 91, 92, 93, 19, 151, 151, 151, 167, - /* 980 */ 151, 151, 207, 196, 30, 218, 22, 175, 176, 1, - /* 990 */ 2, 53, 167, 167, 167, 151, 167, 167, 151, 151, - /* 1000 */ 175, 176, 175, 176, 175, 176, 50, 51, 221, 23, - /* 1010 */ 53, 167, 22, 22, 167, 167, 103, 168, 22, 110, - /* 1020 */ 19, 105, 175, 176, 20, 69, 70, 71, 72, 73, - /* 1030 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83, - /* 1040 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 1050 */ 19, 151, 151, 151, 167, 151, 207, 24, 44, 215, - /* 1060 */ 60, 26, 175, 176, 54, 54, 240, 167, 167, 167, - /* 1070 */ 240, 167, 151, 151, 151, 175, 176, 175, 176, 175, - /* 1080 */ 176, 50, 51, 139, 151, 22, 105, 119, 167, 167, - /* 1090 */ 167, 5, 1, 36, 28, 77, 175, 176, 175, 176, - /* 1100 */ 167, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 1110 */ 79, 80, 81, 151, 83, 84, 85, 86, 87, 88, - /* 1120 */ 89, 90, 91, 92, 93, 19, 151, 151, 151, 167, - /* 1130 */ 151, 151, 109, 151, 128, 77, 22, 175, 176, 26, - /* 1140 */ 218, 240, 167, 167, 167, 151, 167, 167, 151, 167, - /* 1150 */ 175, 176, 175, 176, 175, 176, 50, 51, 151, 22, - /* 1160 */ 151, 167, 23, 120, 167, 1, 16, 122, 20, 120, - /* 1170 */ 109, 195, 175, 176, 167, 195, 167, 71, 72, 73, - /* 1180 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83, - /* 1190 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 1200 */ 19, 20, 195, 22, 167, 151, 151, 128, 27, 28, - /* 1210 */ 129, 23, 175, 176, 23, 66, 141, 22, 151, 38, - /* 1220 */ 151, 167, 167, 19, 20, 151, 22, 151, 151, 175, - /* 1230 */ 176, 27, 28, 151, 167, 15, 167, 4, 57, 16, - /* 1240 */ 151, 167, 38, 167, 167, 3, 166, 248, 67, 167, - /* 1250 */ 195, 175, 176, 181, 181, 150, 167, 175, 176, 251, - /* 1260 */ 6, 57, 151, 151, 175, 176, 151, 151, 87, 88, - /* 1270 */ 89, 67, 151, 162, 151, 94, 95, 96, 167, 167, - /* 1280 */ 99, 251, 167, 167, 152, 151, 175, 176, 167, 151, - /* 1290 */ 167, 87, 88, 151, 150, 150, 175, 176, 94, 95, - /* 1300 */ 96, 167, 150, 99, 151, 167, 151, 196, 13, 167, - /* 1310 */ 195, 130, 131, 132, 133, 134, 135, 152, 195, 160, - /* 1320 */ 167, 117, 167, 19, 20, 151, 22, 151, 217, 151, - /* 1330 */ 161, 27, 28, 222, 130, 131, 132, 133, 134, 135, - /* 1340 */ 151, 167, 38, 167, 151, 167, 19, 20, 195, 22, - /* 1350 */ 151, 151, 151, 151, 27, 28, 167, 151, 151, 26, - /* 1360 */ 167, 57, 25, 196, 151, 38, 167, 167, 167, 167, - /* 1370 */ 151, 67, 151, 167, 167, 117, 201, 151, 125, 151, - /* 1380 */ 167, 151, 127, 124, 57, 151, 167, 202, 167, 203, - /* 1390 */ 151, 87, 88, 167, 67, 167, 151, 167, 94, 95, - /* 1400 */ 96, 167, 151, 99, 123, 126, 167, 204, 136, 227, - /* 1410 */ 205, 119, 167, 105, 87, 88, 122, 177, 167, 158, - /* 1420 */ 158, 94, 95, 96, 212, 105, 99, 213, 212, 177, - /* 1430 */ 213, 213, 185, 48, 130, 131, 132, 133, 134, 135, - /* 1440 */ 5, 212, 177, 179, 104, 10, 11, 12, 13, 14, - /* 1450 */ 177, 180, 17, 22, 230, 93, 180, 130, 131, 132, - /* 1460 */ 133, 134, 135, 185, 177, 230, 177, 32, 177, 34, - /* 1470 */ 157, 22, 18, 158, 157, 157, 27, 28, 43, 158, - /* 1480 */ 158, 158, 46, 237, 136, 157, 238, 158, 191, 201, - /* 1490 */ 69, 56, 191, 58, 220, 22, 157, 62, 18, 201, - /* 1500 */ 65, 158, 220, 194, 194, 194, 194, 201, 158, 242, - /* 1510 */ 191, 41, 242, 158, 158, 39, 67, 154, 232, 168, - /* 1520 */ 245, 228, 198, 178, 183, 200, 168, 211, 232, 168, - /* 1530 */ 178, 178, 201, 187, 198, 149, 87, 88, 179, 168, - /* 1540 */ 241, 106, 107, 108, 95, 211, 241, 112, 99, 211, - /* 1550 */ 201, 197, 117, 193, 210, 188, 184, 184, 184, 175, - /* 1560 */ 93, 235, 175, 252, 252, 252, 236, 252, 252, 252, - /* 1570 */ 252, 252, 252, 252, 252, 140, 252, 252, 252, 130, - /* 1580 */ 131, 132, + /* 0 */ 19, 22, 22, 23, 1, 24, 26, 15, 27, 80, + /* 10 */ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + /* 20 */ 91, 92, 93, 94, 95, 108, 109, 110, 27, 28, + /* 30 */ 23, 50, 51, 80, 81, 82, 83, 122, 85, 86, + /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 22, + /* 50 */ 70, 23, 71, 72, 73, 74, 75, 76, 77, 78, + /* 60 */ 79, 80, 81, 82, 83, 122, 85, 86, 87, 88, + /* 70 */ 89, 90, 91, 92, 93, 94, 95, 19, 97, 91, + /* 80 */ 92, 93, 94, 95, 26, 85, 86, 87, 88, 89, + /* 90 */ 90, 91, 92, 93, 94, 95, 27, 28, 97, 98, + /* 100 */ 99, 122, 211, 102, 103, 104, 79, 19, 50, 51, + /* 110 */ 19, 122, 59, 55, 113, 224, 225, 226, 89, 90, + /* 120 */ 91, 92, 93, 94, 95, 23, 27, 28, 26, 71, + /* 130 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 140 */ 82, 83, 51, 85, 86, 87, 88, 89, 90, 91, + /* 150 */ 92, 93, 94, 95, 19, 132, 133, 58, 89, 90, + /* 160 */ 21, 108, 109, 110, 27, 28, 97, 98, 33, 100, + /* 170 */ 7, 8, 119, 120, 22, 19, 107, 42, 109, 27, + /* 180 */ 28, 27, 28, 95, 28, 50, 51, 99, 100, 101, + /* 190 */ 102, 103, 104, 105, 27, 28, 97, 98, 107, 152, + /* 200 */ 112, 132, 133, 112, 65, 69, 71, 72, 73, 74, + /* 210 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 11, + /* 220 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 230 */ 95, 19, 101, 97, 97, 98, 24, 101, 122, 157, + /* 240 */ 12, 99, 103, 112, 102, 103, 104, 152, 22, 97, + /* 250 */ 98, 97, 98, 27, 28, 113, 27, 29, 91, 164, + /* 260 */ 165, 124, 50, 51, 97, 98, 219, 59, 132, 133, + /* 270 */ 134, 22, 23, 45, 66, 47, 212, 213, 124, 140, + /* 280 */ 132, 133, 19, 71, 72, 73, 74, 75, 76, 77, + /* 290 */ 78, 79, 80, 81, 82, 83, 152, 85, 86, 87, + /* 300 */ 88, 89, 90, 91, 92, 93, 94, 95, 164, 165, + /* 310 */ 27, 28, 230, 50, 51, 233, 108, 109, 110, 70, + /* 320 */ 16, 59, 23, 97, 98, 26, 97, 22, 66, 185, + /* 330 */ 12, 187, 27, 28, 71, 72, 73, 74, 75, 76, + /* 340 */ 77, 78, 79, 80, 81, 82, 83, 29, 85, 86, + /* 350 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 19, + /* 360 */ 22, 148, 149, 45, 23, 47, 62, 154, 64, 156, + /* 370 */ 108, 109, 110, 37, 69, 23, 163, 59, 26, 26, + /* 380 */ 97, 98, 144, 145, 146, 147, 152, 200, 52, 23, + /* 390 */ 50, 51, 26, 22, 89, 90, 60, 210, 7, 8, + /* 400 */ 9, 138, 97, 22, 23, 26, 101, 26, 174, 175, + /* 410 */ 197, 71, 72, 73, 74, 75, 76, 77, 78, 79, + /* 420 */ 80, 81, 82, 83, 16, 85, 86, 87, 88, 89, + /* 430 */ 90, 91, 92, 93, 94, 95, 19, 132, 133, 134, + /* 440 */ 23, 152, 208, 209, 140, 152, 152, 111, 195, 196, + /* 450 */ 98, 70, 163, 160, 152, 23, 22, 164, 165, 246, + /* 460 */ 207, 27, 152, 174, 175, 171, 172, 50, 51, 137, + /* 470 */ 62, 139, 64, 171, 172, 222, 124, 27, 138, 24, + /* 480 */ 163, 89, 90, 130, 174, 175, 197, 163, 71, 72, + /* 490 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + /* 500 */ 83, 22, 85, 86, 87, 88, 89, 90, 91, 92, + /* 510 */ 93, 94, 95, 19, 197, 181, 182, 23, 208, 209, + /* 520 */ 152, 197, 26, 189, 132, 133, 232, 224, 225, 226, + /* 530 */ 152, 97, 91, 26, 232, 116, 212, 213, 152, 222, + /* 540 */ 121, 152, 174, 175, 50, 51, 243, 97, 22, 23, + /* 550 */ 22, 234, 174, 175, 177, 23, 239, 116, 163, 177, + /* 560 */ 174, 175, 121, 174, 175, 71, 72, 73, 74, 75, + /* 570 */ 76, 77, 78, 79, 80, 81, 82, 83, 24, 85, + /* 580 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 590 */ 19, 23, 197, 11, 23, 227, 70, 208, 220, 152, + /* 600 */ 31, 224, 225, 226, 35, 98, 224, 225, 226, 108, + /* 610 */ 109, 110, 115, 152, 117, 118, 27, 222, 49, 123, + /* 620 */ 24, 50, 51, 27, 0, 1, 2, 224, 225, 226, + /* 630 */ 166, 124, 168, 169, 239, 174, 175, 170, 171, 172, + /* 640 */ 22, 194, 71, 72, 73, 74, 75, 76, 77, 78, + /* 650 */ 79, 80, 81, 82, 83, 152, 85, 86, 87, 88, + /* 660 */ 89, 90, 91, 92, 93, 94, 95, 19, 22, 208, + /* 670 */ 24, 23, 195, 196, 170, 171, 172, 174, 175, 152, + /* 680 */ 26, 152, 152, 152, 207, 152, 97, 152, 23, 152, + /* 690 */ 51, 244, 152, 97, 152, 247, 248, 23, 50, 51, + /* 700 */ 26, 174, 175, 174, 175, 174, 175, 174, 175, 174, + /* 710 */ 175, 174, 175, 23, 174, 175, 174, 175, 188, 71, + /* 720 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 730 */ 82, 83, 152, 85, 86, 87, 88, 89, 90, 91, + /* 740 */ 92, 93, 94, 95, 19, 152, 107, 152, 33, 24, + /* 750 */ 152, 100, 101, 27, 174, 175, 152, 42, 152, 23, + /* 760 */ 152, 26, 152, 23, 152, 26, 152, 174, 175, 174, + /* 770 */ 175, 152, 174, 175, 23, 50, 51, 26, 174, 175, + /* 780 */ 174, 175, 174, 175, 174, 175, 174, 175, 174, 175, + /* 790 */ 163, 119, 120, 174, 175, 19, 71, 72, 73, 74, + /* 800 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 152, + /* 810 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 820 */ 95, 66, 152, 97, 197, 23, 50, 51, 26, 53, + /* 830 */ 23, 174, 175, 26, 23, 23, 23, 26, 26, 26, + /* 840 */ 36, 106, 146, 147, 174, 175, 19, 71, 72, 73, + /* 850 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 860 */ 152, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 870 */ 94, 95, 152, 196, 119, 120, 19, 50, 51, 168, + /* 880 */ 169, 26, 174, 175, 207, 28, 152, 249, 250, 152, + /* 890 */ 163, 163, 163, 163, 174, 175, 163, 19, 71, 72, + /* 900 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + /* 910 */ 83, 152, 85, 86, 87, 88, 89, 90, 91, 92, + /* 920 */ 93, 94, 95, 152, 197, 197, 197, 197, 50, 51, + /* 930 */ 197, 194, 36, 174, 175, 191, 192, 152, 191, 192, + /* 940 */ 163, 152, 66, 124, 152, 174, 175, 152, 19, 71, + /* 950 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 960 */ 82, 83, 152, 85, 86, 87, 88, 89, 90, 91, + /* 970 */ 92, 93, 94, 95, 197, 152, 100, 188, 152, 50, + /* 980 */ 51, 152, 152, 188, 174, 175, 252, 152, 94, 95, + /* 990 */ 152, 152, 152, 1, 2, 152, 152, 174, 175, 19, + /* 1000 */ 152, 72, 73, 74, 75, 76, 77, 78, 79, 80, + /* 1010 */ 81, 82, 83, 152, 85, 86, 87, 88, 89, 90, + /* 1020 */ 91, 92, 93, 94, 95, 152, 188, 188, 22, 194, + /* 1030 */ 50, 51, 240, 173, 194, 174, 175, 252, 194, 152, + /* 1040 */ 36, 181, 28, 152, 23, 219, 122, 174, 175, 219, + /* 1050 */ 221, 152, 152, 73, 74, 75, 76, 77, 78, 79, + /* 1060 */ 80, 81, 82, 83, 152, 85, 86, 87, 88, 89, + /* 1070 */ 90, 91, 92, 93, 94, 95, 19, 20, 152, 22, + /* 1080 */ 23, 194, 152, 240, 27, 28, 174, 175, 240, 19, + /* 1090 */ 20, 26, 22, 194, 194, 38, 22, 27, 28, 152, + /* 1100 */ 23, 22, 152, 116, 174, 175, 152, 23, 38, 152, + /* 1110 */ 23, 152, 221, 152, 57, 152, 23, 163, 50, 51, + /* 1120 */ 194, 174, 175, 66, 174, 175, 69, 57, 174, 175, + /* 1130 */ 40, 174, 175, 174, 175, 174, 175, 174, 175, 69, + /* 1140 */ 22, 53, 74, 75, 30, 53, 89, 90, 22, 22, + /* 1150 */ 152, 197, 23, 96, 97, 98, 22, 152, 101, 89, + /* 1160 */ 90, 91, 208, 209, 152, 53, 96, 97, 98, 101, + /* 1170 */ 22, 101, 174, 175, 152, 19, 20, 105, 22, 174, + /* 1180 */ 175, 112, 19, 27, 28, 20, 174, 175, 24, 132, + /* 1190 */ 133, 134, 135, 136, 38, 44, 174, 175, 107, 61, + /* 1200 */ 54, 26, 132, 133, 134, 135, 136, 54, 107, 22, + /* 1210 */ 5, 140, 1, 57, 36, 111, 122, 28, 79, 79, + /* 1220 */ 131, 123, 66, 19, 20, 69, 22, 1, 16, 20, + /* 1230 */ 125, 27, 28, 123, 111, 120, 23, 131, 23, 16, + /* 1240 */ 68, 142, 38, 15, 22, 89, 90, 3, 167, 4, + /* 1250 */ 248, 251, 96, 97, 98, 180, 180, 101, 251, 151, + /* 1260 */ 6, 57, 151, 13, 151, 26, 25, 151, 161, 202, + /* 1270 */ 153, 162, 153, 69, 130, 128, 203, 19, 20, 127, + /* 1280 */ 22, 126, 204, 129, 22, 27, 28, 205, 132, 133, + /* 1290 */ 134, 135, 136, 89, 90, 231, 38, 95, 137, 179, + /* 1300 */ 96, 97, 98, 206, 179, 101, 122, 107, 159, 159, + /* 1310 */ 125, 231, 216, 228, 107, 57, 184, 217, 216, 176, + /* 1320 */ 217, 176, 48, 106, 18, 184, 158, 69, 159, 158, + /* 1330 */ 46, 71, 237, 176, 176, 176, 132, 133, 134, 135, + /* 1340 */ 136, 217, 176, 137, 216, 178, 158, 89, 90, 179, + /* 1350 */ 176, 159, 179, 159, 96, 97, 98, 159, 159, 101, + /* 1360 */ 5, 158, 202, 22, 18, 10, 11, 12, 13, 14, + /* 1370 */ 190, 238, 17, 190, 158, 193, 41, 159, 202, 193, + /* 1380 */ 159, 202, 245, 193, 193, 223, 190, 32, 159, 34, + /* 1390 */ 132, 133, 134, 135, 136, 159, 39, 155, 43, 150, + /* 1400 */ 223, 177, 201, 178, 177, 186, 66, 199, 177, 152, + /* 1410 */ 253, 56, 215, 152, 182, 152, 202, 152, 63, 152, + /* 1420 */ 152, 66, 67, 242, 229, 152, 174, 152, 152, 152, + /* 1430 */ 152, 152, 152, 152, 199, 242, 202, 152, 198, 152, + /* 1440 */ 152, 152, 183, 192, 152, 215, 152, 183, 215, 183, + /* 1450 */ 152, 241, 214, 152, 211, 152, 152, 211, 211, 152, + /* 1460 */ 152, 241, 152, 152, 152, 152, 152, 152, 152, 114, + /* 1470 */ 152, 152, 235, 152, 152, 152, 174, 187, 95, 174, + /* 1480 */ 253, 253, 253, 253, 236, 253, 253, 253, 253, 253, + /* 1490 */ 253, 253, 253, 253, 253, 253, 141, }; -#define YY_SHIFT_USE_DFLT (-82) -#define YY_SHIFT_COUNT (419) -#define YY_SHIFT_MIN (-81) -#define YY_SHIFT_MAX (1480) +#define YY_SHIFT_USE_DFLT (-86) +#define YY_SHIFT_COUNT (429) +#define YY_SHIFT_MIN (-85) +#define YY_SHIFT_MAX (1383) static const short yy_shift_ofst[] = { - /* 0 */ 988, 1204, 1435, 1204, 1304, 1304, 67, 67, 1, -19, - /* 10 */ 1304, 1304, 1304, 1304, 427, 81, 131, 131, 806, 1181, - /* 20 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, - /* 30 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, - /* 40 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1327, 1304, - /* 50 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, - /* 60 */ 1304, 1304, 52, 81, 81, 476, 476, 395, 1258, 56, - /* 70 */ 731, 656, 581, 506, 431, 356, 281, 206, 881, 881, - /* 80 */ 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, - /* 90 */ 881, 881, 881, 956, 881, 1031, 1106, 1106, -69, -45, - /* 100 */ -45, -45, -45, -45, 0, 29, -12, 81, 81, 81, - /* 110 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - /* 120 */ 81, 81, 81, 355, 440, 81, 81, 81, 81, 81, - /* 130 */ 504, 411, 395, 818, 1467, -82, -82, -82, 1449, 86, - /* 140 */ 439, 439, 306, 357, 302, 72, 318, 246, 169, 81, - /* 150 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - /* 160 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - /* 170 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - /* 180 */ 81, 81, 315, 315, 315, 572, 1258, 1258, 1258, -82, - /* 190 */ -82, -82, 132, 132, 208, 568, 568, 568, 516, 503, - /* 200 */ 214, 452, 363, 228, 119, 119, 119, 119, 359, 126, - /* 210 */ 119, 119, 584, 293, 604, 106, 11, 288, 288, 513, - /* 220 */ 11, 513, 295, 813, 395, 831, 395, 831, 595, 831, - /* 230 */ 288, 649, 498, 498, 395, 154, 273, 699, 1476, 1292, - /* 240 */ 1292, 1470, 1470, 1292, 1473, 1421, 1255, 1480, 1480, 1480, - /* 250 */ 1480, 1292, 1454, 1255, 1473, 1421, 1421, 1255, 1292, 1454, - /* 260 */ 1348, 1436, 1292, 1292, 1454, 1292, 1454, 1292, 1454, 1431, - /* 270 */ 1320, 1320, 1320, 1385, 1362, 1362, 1431, 1320, 1340, 1320, - /* 280 */ 1385, 1320, 1320, 1294, 1308, 1294, 1308, 1294, 1308, 1292, - /* 290 */ 1292, 1272, 1279, 1281, 1253, 1259, 1255, 1258, 1337, 1333, - /* 300 */ 1295, 1295, 1254, 1254, 1254, 1254, -82, -82, -82, -82, - /* 310 */ -82, -82, 339, 399, 618, 326, 620, -81, 669, 477, - /* 320 */ 661, 585, 377, 280, 244, 232, 25, -1, 373, 227, - /* 330 */ 215, 1233, 1242, 1195, 1075, 1220, 1149, 1223, 1191, 1188, - /* 340 */ 1081, 1113, 1079, 1061, 1049, 1148, 1045, 1150, 1164, 1043, - /* 350 */ 1139, 1137, 1113, 1114, 1006, 1058, 1018, 1023, 1066, 1057, - /* 360 */ 968, 1091, 1086, 1063, 981, 944, 1011, 1035, 1010, 1000, - /* 370 */ 1014, 916, 1033, 1004, 1001, 909, 913, 996, 957, 991, - /* 380 */ 990, 986, 964, 938, 954, 917, 889, 897, 912, 910, - /* 390 */ 797, 886, 761, 838, 528, 726, 735, 765, 665, 726, - /* 400 */ 592, 586, 540, 523, 491, 487, 435, 401, 397, 387, - /* 410 */ 249, 216, 185, 127, 110, 51, 82, 143, 15, 48, + /* 0 */ 992, 1057, 1355, 1156, 1204, 1204, 1, 262, -19, 135, + /* 10 */ 135, 776, 1204, 1204, 1204, 1204, 69, 69, 53, 208, + /* 20 */ 283, 755, 58, 725, 648, 571, 494, 417, 340, 263, + /* 30 */ 212, 827, 827, 827, 827, 827, 827, 827, 827, 827, + /* 40 */ 827, 827, 827, 827, 827, 827, 878, 827, 929, 980, + /* 50 */ 980, 1070, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, + /* 60 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, + /* 70 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, + /* 80 */ 1258, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, + /* 90 */ 1204, 1204, 1204, 1204, -71, -47, -47, -47, -47, -47, + /* 100 */ 0, 29, -12, 283, 283, 139, 91, 392, 392, 894, + /* 110 */ 672, 726, 1383, -86, -86, -86, 88, 318, 318, 99, + /* 120 */ 381, -20, 283, 283, 283, 283, 283, 283, 283, 283, + /* 130 */ 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + /* 140 */ 283, 283, 283, 283, 624, 876, 726, 672, 1340, 1340, + /* 150 */ 1340, 1340, 1340, 1340, -86, -86, -86, 305, 136, 136, + /* 160 */ 142, 167, 226, 154, 137, 152, 283, 283, 283, 283, + /* 170 */ 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + /* 180 */ 283, 283, 283, 336, 336, 336, 283, 283, 352, 283, + /* 190 */ 283, 283, 283, 283, 228, 283, 283, 283, 283, 283, + /* 200 */ 283, 283, 283, 283, 283, 501, 569, 596, 596, 596, + /* 210 */ 507, 497, 441, 391, 353, 156, 156, 857, 353, 857, + /* 220 */ 735, 813, 639, 715, 156, 332, 715, 715, 496, 419, + /* 230 */ 646, 1357, 1184, 1184, 1335, 1335, 1184, 1341, 1260, 1144, + /* 240 */ 1346, 1346, 1346, 1346, 1184, 1306, 1144, 1341, 1260, 1260, + /* 250 */ 1144, 1184, 1306, 1206, 1284, 1184, 1184, 1306, 1184, 1306, + /* 260 */ 1184, 1306, 1262, 1207, 1207, 1207, 1274, 1262, 1207, 1217, + /* 270 */ 1207, 1274, 1207, 1207, 1185, 1200, 1185, 1200, 1185, 1200, + /* 280 */ 1184, 1184, 1161, 1262, 1202, 1202, 1262, 1154, 1155, 1147, + /* 290 */ 1152, 1144, 1241, 1239, 1250, 1250, 1254, 1254, 1254, 1254, + /* 300 */ -86, -86, -86, -86, -86, -86, 1068, 304, 526, 249, + /* 310 */ 408, -83, 434, 812, 27, 811, 807, 802, 751, 589, + /* 320 */ 651, 163, 131, 674, 366, 450, 299, 148, 23, 102, + /* 330 */ 229, -21, 1245, 1244, 1222, 1099, 1228, 1172, 1223, 1215, + /* 340 */ 1213, 1115, 1106, 1123, 1110, 1209, 1105, 1212, 1226, 1098, + /* 350 */ 1089, 1140, 1139, 1104, 1189, 1178, 1094, 1211, 1205, 1187, + /* 360 */ 1101, 1071, 1153, 1175, 1146, 1138, 1151, 1091, 1164, 1165, + /* 370 */ 1163, 1069, 1072, 1148, 1112, 1134, 1127, 1129, 1126, 1092, + /* 380 */ 1114, 1118, 1088, 1090, 1093, 1087, 1084, 987, 1079, 1077, + /* 390 */ 1074, 1065, 924, 1021, 1014, 1004, 1006, 819, 739, 896, + /* 400 */ 855, 804, 739, 740, 736, 690, 654, 665, 618, 582, + /* 410 */ 568, 528, 554, 379, 532, 479, 455, 379, 432, 371, + /* 420 */ 341, 28, 338, 116, -11, -57, -85, 7, -8, 3, }; -#define YY_REDUCE_USE_DFLT (-143) -#define YY_REDUCE_COUNT (311) -#define YY_REDUCE_MIN (-142) -#define YY_REDUCE_MAX (1387) +#define YY_REDUCE_USE_DFLT (-110) +#define YY_REDUCE_COUNT (305) +#define YY_REDUCE_MIN (-109) +#define YY_REDUCE_MAX (1323) static const short yy_reduce_ofst[] = { - /* 0 */ -142, 1111, 92, 151, 241, 161, 150, 93, 85, 324, - /* 10 */ 386, 313, 320, 229, -6, 310, 536, 485, -72, 1121, - /* 20 */ 1089, 1082, 1076, 1054, 1037, 997, 979, 977, 975, 962, - /* 30 */ 923, 921, 904, 902, 900, 887, 847, 829, 827, 825, - /* 40 */ 812, 771, 769, 754, 752, 750, 737, 679, 677, 675, - /* 50 */ 662, 623, 619, 617, 613, 602, 600, 587, 537, 527, - /* 60 */ 472, 376, 480, 450, 226, 453, 398, 390, 426, 420, - /* 70 */ 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, - /* 80 */ 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, - /* 90 */ 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, - /* 100 */ 420, 420, 420, 420, 420, 420, 420, 1153, 922, 1123, - /* 110 */ 1115, 1055, 1007, 980, 976, 901, 844, 830, 767, 826, - /* 120 */ 682, 694, 707, 482, 583, 681, 680, 676, 531, 27, - /* 130 */ 787, 562, 521, 420, 420, 420, 420, 420, 773, 741, - /* 140 */ 674, 670, 1067, 1251, 1245, 1239, 1234, 591, 591, 1230, - /* 150 */ 1228, 1226, 1221, 1219, 1213, 1207, 1206, 1202, 1201, 1200, - /* 160 */ 1199, 1193, 1189, 1178, 1176, 1174, 1155, 1142, 1138, 1134, - /* 170 */ 1116, 1112, 1077, 1074, 1069, 1067, 1009, 994, 982, 933, - /* 180 */ 848, 757, 849, 775, 628, 611, 745, 710, 672, 469, - /* 190 */ 488, 573, 1387, 1384, 1367, 1374, 1373, 1372, 1344, 1354, - /* 200 */ 1360, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1330, 1326, - /* 210 */ 1354, 1354, 1344, 1371, 1336, 1386, 1349, 1338, 1334, 1305, - /* 220 */ 1331, 1299, 1359, 1346, 1361, 1353, 1358, 1352, 1341, 1345, - /* 230 */ 1316, 1293, 1296, 1286, 1351, 1325, 1324, 1363, 1275, 1356, - /* 240 */ 1355, 1270, 1267, 1350, 1282, 1319, 1306, 1312, 1311, 1310, - /* 250 */ 1309, 1343, 1339, 1298, 1274, 1301, 1297, 1288, 1329, 1328, - /* 260 */ 1248, 1246, 1323, 1322, 1318, 1321, 1317, 1315, 1313, 1276, - /* 270 */ 1291, 1289, 1287, 1278, 1235, 1224, 1271, 1273, 1264, 1265, - /* 280 */ 1247, 1252, 1240, 1218, 1229, 1217, 1216, 1214, 1212, 1262, - /* 290 */ 1261, 1182, 1205, 1203, 1186, 1185, 1175, 1167, 1169, 1159, - /* 300 */ 1165, 1132, 1152, 1145, 1144, 1105, 1030, 1008, 999, 1073, - /* 310 */ 1072, 1080, + /* 0 */ 238, 954, 213, 289, 310, 234, 144, 317, -109, 382, + /* 10 */ 377, 303, 461, 389, 378, 368, 302, 294, 253, 395, + /* 20 */ 293, 324, 403, 403, 403, 403, 403, 403, 403, 403, + /* 30 */ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + /* 40 */ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + /* 50 */ 403, 1022, 1012, 1005, 998, 963, 961, 959, 957, 950, + /* 60 */ 947, 930, 912, 873, 861, 823, 810, 771, 759, 720, + /* 70 */ 708, 670, 657, 619, 614, 612, 610, 608, 606, 604, + /* 80 */ 598, 595, 593, 580, 542, 540, 537, 535, 533, 531, + /* 90 */ 529, 527, 503, 386, 403, 403, 403, 403, 403, 403, + /* 100 */ 403, 403, 403, 95, 447, 82, 334, 504, 467, 403, + /* 110 */ 477, 464, 403, 403, 403, 403, 860, 747, 744, 785, + /* 120 */ 638, 638, 926, 891, 900, 899, 887, 844, 840, 835, + /* 130 */ 848, 830, 843, 829, 792, 839, 826, 737, 838, 795, + /* 140 */ 789, 47, 734, 530, 696, 777, 711, 677, 733, 730, + /* 150 */ 729, 728, 727, 627, 448, 64, 187, 1305, 1302, 1252, + /* 160 */ 1290, 1273, 1323, 1322, 1321, 1319, 1318, 1316, 1315, 1314, + /* 170 */ 1313, 1312, 1311, 1310, 1308, 1307, 1304, 1303, 1301, 1298, + /* 180 */ 1294, 1292, 1289, 1266, 1264, 1259, 1288, 1287, 1238, 1285, + /* 190 */ 1281, 1280, 1279, 1278, 1251, 1277, 1276, 1275, 1273, 1268, + /* 200 */ 1267, 1265, 1263, 1261, 1257, 1248, 1237, 1247, 1246, 1243, + /* 210 */ 1238, 1240, 1235, 1249, 1234, 1233, 1230, 1220, 1214, 1210, + /* 220 */ 1225, 1219, 1232, 1231, 1197, 1195, 1227, 1224, 1201, 1208, + /* 230 */ 1242, 1137, 1236, 1229, 1193, 1181, 1221, 1177, 1196, 1179, + /* 240 */ 1191, 1190, 1186, 1182, 1218, 1216, 1176, 1162, 1183, 1180, + /* 250 */ 1160, 1199, 1203, 1133, 1095, 1198, 1194, 1188, 1192, 1171, + /* 260 */ 1169, 1168, 1173, 1174, 1166, 1159, 1141, 1170, 1158, 1167, + /* 270 */ 1157, 1132, 1145, 1143, 1124, 1128, 1103, 1102, 1100, 1096, + /* 280 */ 1150, 1149, 1085, 1125, 1080, 1064, 1120, 1097, 1082, 1078, + /* 290 */ 1073, 1067, 1109, 1107, 1119, 1117, 1116, 1113, 1111, 1108, + /* 300 */ 1007, 1000, 1002, 1076, 1075, 1081, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 636, 872, 960, 960, 872, 872, 960, 960, 960, 762, - /* 10 */ 960, 960, 960, 870, 960, 960, 790, 790, 934, 960, - /* 20 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 30 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 40 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 50 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 60 */ 960, 960, 960, 960, 960, 960, 960, 677, 766, 796, - /* 70 */ 960, 960, 960, 960, 960, 960, 960, 960, 933, 935, - /* 80 */ 804, 803, 913, 777, 801, 794, 798, 873, 866, 867, - /* 90 */ 865, 869, 874, 960, 797, 833, 850, 832, 844, 849, - /* 100 */ 856, 848, 845, 835, 834, 836, 837, 960, 960, 960, - /* 110 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 120 */ 960, 960, 960, 662, 731, 960, 960, 960, 960, 960, - /* 130 */ 960, 960, 960, 838, 839, 853, 852, 851, 960, 669, - /* 140 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 150 */ 940, 938, 960, 885, 960, 960, 960, 960, 960, 960, - /* 160 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 170 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 180 */ 960, 642, 762, 762, 762, 636, 960, 960, 960, 952, - /* 190 */ 766, 756, 960, 960, 960, 960, 960, 960, 960, 960, - /* 200 */ 960, 960, 960, 960, 806, 745, 923, 925, 960, 906, - /* 210 */ 743, 664, 764, 679, 754, 644, 800, 779, 779, 918, - /* 220 */ 800, 918, 702, 725, 960, 790, 960, 790, 699, 790, - /* 230 */ 779, 868, 960, 960, 960, 763, 754, 960, 945, 770, - /* 240 */ 770, 937, 937, 770, 812, 735, 800, 742, 742, 742, - /* 250 */ 742, 770, 659, 800, 812, 735, 735, 800, 770, 659, - /* 260 */ 912, 910, 770, 770, 659, 770, 659, 770, 659, 878, - /* 270 */ 733, 733, 733, 717, 882, 882, 878, 733, 702, 733, - /* 280 */ 717, 733, 733, 783, 778, 783, 778, 783, 778, 770, - /* 290 */ 770, 960, 795, 784, 793, 791, 800, 960, 665, 720, - /* 300 */ 652, 652, 641, 641, 641, 641, 957, 957, 952, 704, - /* 310 */ 704, 687, 960, 960, 960, 960, 960, 960, 960, 887, - /* 320 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 330 */ 960, 960, 637, 947, 960, 960, 944, 960, 960, 960, - /* 340 */ 960, 805, 960, 960, 960, 960, 960, 960, 960, 960, - /* 350 */ 960, 960, 922, 960, 960, 960, 960, 960, 960, 960, - /* 360 */ 916, 960, 960, 960, 960, 960, 960, 909, 908, 960, - /* 370 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 380 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 390 */ 960, 960, 960, 960, 960, 792, 960, 785, 960, 871, - /* 400 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - /* 410 */ 748, 821, 960, 820, 824, 819, 671, 960, 650, 960, - /* 420 */ 633, 638, 956, 959, 958, 955, 954, 953, 948, 946, - /* 430 */ 943, 942, 941, 939, 936, 932, 891, 889, 896, 895, - /* 440 */ 894, 893, 892, 890, 888, 886, 807, 802, 799, 931, - /* 450 */ 884, 744, 741, 740, 658, 949, 915, 924, 811, 810, - /* 460 */ 813, 921, 920, 919, 917, 914, 901, 809, 808, 736, - /* 470 */ 876, 875, 661, 905, 904, 903, 907, 911, 902, 772, - /* 480 */ 660, 657, 668, 723, 724, 732, 730, 729, 728, 727, - /* 490 */ 726, 722, 670, 678, 716, 701, 700, 881, 883, 880, - /* 500 */ 879, 709, 708, 714, 713, 712, 711, 710, 707, 706, - /* 510 */ 705, 698, 697, 703, 696, 719, 718, 715, 695, 739, - /* 520 */ 738, 737, 734, 694, 693, 692, 824, 691, 690, 830, - /* 530 */ 829, 817, 860, 759, 758, 757, 769, 768, 781, 780, - /* 540 */ 815, 814, 782, 767, 761, 760, 776, 775, 774, 773, - /* 550 */ 765, 755, 787, 789, 788, 786, 862, 771, 859, 930, - /* 560 */ 929, 928, 927, 926, 864, 863, 831, 828, 682, 683, - /* 570 */ 899, 898, 900, 897, 685, 684, 681, 680, 861, 750, - /* 580 */ 749, 857, 854, 846, 842, 858, 855, 847, 843, 841, - /* 590 */ 840, 826, 825, 823, 822, 818, 827, 673, 751, 747, - /* 600 */ 746, 816, 753, 752, 689, 688, 686, 667, 666, 663, - /* 610 */ 656, 654, 653, 655, 651, 649, 648, 647, 646, 645, - /* 620 */ 676, 675, 674, 672, 671, 643, 640, 639, 635, 634, - /* 630 */ 632, + /* 0 */ 647, 964, 964, 964, 878, 878, 969, 964, 774, 802, + /* 10 */ 802, 938, 969, 969, 969, 876, 969, 969, 969, 964, + /* 20 */ 969, 778, 808, 969, 969, 969, 969, 969, 969, 969, + /* 30 */ 969, 937, 939, 816, 815, 918, 789, 813, 806, 810, + /* 40 */ 879, 872, 873, 871, 875, 880, 969, 809, 841, 856, + /* 50 */ 840, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 60 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 70 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 80 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 90 */ 969, 969, 969, 969, 850, 855, 862, 854, 851, 843, + /* 100 */ 842, 844, 845, 969, 969, 673, 739, 969, 969, 846, + /* 110 */ 969, 685, 847, 859, 858, 857, 680, 969, 969, 969, + /* 120 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 130 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 140 */ 969, 969, 969, 969, 647, 964, 969, 969, 964, 964, + /* 150 */ 964, 964, 964, 964, 956, 778, 768, 969, 969, 969, + /* 160 */ 969, 969, 969, 969, 969, 969, 969, 944, 942, 969, + /* 170 */ 891, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 180 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 190 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 200 */ 969, 969, 969, 969, 653, 969, 911, 774, 774, 774, + /* 210 */ 776, 754, 766, 655, 812, 791, 791, 923, 812, 923, + /* 220 */ 710, 733, 707, 802, 791, 874, 802, 802, 775, 766, + /* 230 */ 969, 949, 782, 782, 941, 941, 782, 821, 743, 812, + /* 240 */ 750, 750, 750, 750, 782, 670, 812, 821, 743, 743, + /* 250 */ 812, 782, 670, 917, 915, 782, 782, 670, 782, 670, + /* 260 */ 782, 670, 884, 741, 741, 741, 725, 884, 741, 710, + /* 270 */ 741, 725, 741, 741, 795, 790, 795, 790, 795, 790, + /* 280 */ 782, 782, 969, 884, 888, 888, 884, 807, 796, 805, + /* 290 */ 803, 812, 676, 728, 663, 663, 652, 652, 652, 652, + /* 300 */ 961, 961, 956, 712, 712, 695, 969, 969, 969, 969, + /* 310 */ 969, 969, 687, 969, 893, 969, 969, 969, 969, 969, + /* 320 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 330 */ 969, 828, 969, 648, 951, 969, 969, 948, 969, 969, + /* 340 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 350 */ 969, 969, 969, 969, 969, 969, 921, 969, 969, 969, + /* 360 */ 969, 969, 969, 914, 913, 969, 969, 969, 969, 969, + /* 370 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 380 */ 969, 969, 969, 969, 969, 969, 969, 757, 969, 969, + /* 390 */ 969, 761, 969, 969, 969, 969, 969, 969, 804, 969, + /* 400 */ 797, 969, 877, 969, 969, 969, 969, 969, 969, 969, + /* 410 */ 969, 969, 969, 966, 969, 969, 969, 965, 969, 969, + /* 420 */ 969, 969, 969, 830, 969, 829, 833, 969, 661, 969, + /* 430 */ 644, 649, 960, 963, 962, 959, 958, 957, 952, 950, + /* 440 */ 947, 946, 945, 943, 940, 936, 897, 895, 902, 901, + /* 450 */ 900, 899, 898, 896, 894, 892, 818, 817, 814, 811, + /* 460 */ 753, 935, 890, 752, 749, 748, 669, 953, 920, 929, + /* 470 */ 928, 927, 822, 926, 925, 924, 922, 919, 906, 820, + /* 480 */ 819, 744, 882, 881, 672, 910, 909, 908, 912, 916, + /* 490 */ 907, 784, 751, 671, 668, 675, 679, 731, 732, 740, + /* 500 */ 738, 737, 736, 735, 734, 730, 681, 686, 724, 709, + /* 510 */ 708, 717, 716, 722, 721, 720, 719, 718, 715, 714, + /* 520 */ 713, 706, 705, 711, 704, 727, 726, 723, 703, 747, + /* 530 */ 746, 745, 742, 702, 701, 700, 833, 699, 698, 838, + /* 540 */ 837, 866, 826, 755, 759, 758, 762, 763, 771, 770, + /* 550 */ 769, 780, 781, 793, 792, 824, 823, 794, 779, 773, + /* 560 */ 772, 788, 787, 786, 785, 777, 767, 799, 798, 868, + /* 570 */ 783, 867, 865, 934, 933, 932, 931, 930, 870, 967, + /* 580 */ 968, 887, 889, 886, 801, 800, 885, 869, 839, 836, + /* 590 */ 690, 691, 905, 904, 903, 693, 692, 689, 688, 863, + /* 600 */ 860, 852, 864, 861, 853, 849, 848, 834, 832, 831, + /* 610 */ 827, 835, 760, 756, 825, 765, 764, 697, 696, 694, + /* 620 */ 678, 677, 674, 667, 665, 664, 666, 662, 660, 659, + /* 630 */ 658, 657, 656, 684, 683, 682, 654, 651, 650, 646, + /* 640 */ 645, 643, }; /* The next table maps tokens into fallback tokens. If a construct @@ -115159,6 +116170,7 @@ static const YYCODETYPE yyFallback[] = { 27, /* OFFSET => ID */ 27, /* PRAGMA => ID */ 27, /* RAISE => ID */ + 27, /* RECURSIVE => ID */ 27, /* REPLACE => ID */ 27, /* RESTRICT => ID */ 27, /* ROW => ID */ @@ -115166,6 +116178,7 @@ static const YYCODETYPE yyFallback[] = { 27, /* VACUUM => ID */ 27, /* VIEW => ID */ 27, /* VIRTUAL => ID */ + 27, /* WITH => ID */ 27, /* REINDEX => ID */ 27, /* RENAME => ID */ 27, /* CTIME_KW => ID */ @@ -115261,55 +116274,56 @@ static const char *const yyTokenName[] = { "EACH", "FAIL", "FOR", "IGNORE", "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH", "NO", "KEY", "OF", "OFFSET", - "PRAGMA", "RAISE", "REPLACE", "RESTRICT", - "ROW", "TRIGGER", "VACUUM", "VIEW", - "VIRTUAL", "REINDEX", "RENAME", "CTIME_KW", - "ANY", "OR", "AND", "IS", - "BETWEEN", "IN", "ISNULL", "NOTNULL", - "NE", "EQ", "GT", "LE", - "LT", "GE", "ESCAPE", "BITAND", - "BITOR", "LSHIFT", "RSHIFT", "PLUS", - "MINUS", "STAR", "SLASH", "REM", - "CONCAT", "COLLATE", "BITNOT", "STRING", - "JOIN_KW", "CONSTRAINT", "DEFAULT", "NULL", - "PRIMARY", "UNIQUE", "CHECK", "REFERENCES", - "AUTOINCR", "ON", "INSERT", "DELETE", - "UPDATE", "SET", "DEFERRABLE", "FOREIGN", - "DROP", "UNION", "ALL", "EXCEPT", - "INTERSECT", "SELECT", "DISTINCT", "DOT", - "FROM", "JOIN", "USING", "ORDER", - "GROUP", "HAVING", "LIMIT", "WHERE", - "INTO", "VALUES", "INTEGER", "FLOAT", - "BLOB", "REGISTER", "VARIABLE", "CASE", - "WHEN", "THEN", "ELSE", "INDEX", - "ALTER", "ADD", "error", "input", - "cmdlist", "ecmd", "explain", "cmdx", - "cmd", "transtype", "trans_opt", "nm", - "savepoint_opt", "create_table", "create_table_args", "createkw", - "temp", "ifnotexists", "dbnm", "columnlist", - "conslist_opt", "table_options", "select", "column", - "columnid", "type", "carglist", "id", - "ids", "typetoken", "typename", "signed", - "plus_num", "minus_num", "ccons", "term", - "expr", "onconf", "sortorder", "autoinc", - "idxlist_opt", "refargs", "defer_subclause", "refarg", - "refact", "init_deferred_pred_opt", "conslist", "tconscomma", - "tcons", "idxlist", "defer_subclause_opt", "orconf", - "resolvetype", "raisetype", "ifexists", "fullname", - "oneselect", "multiselect_op", "distinct", "selcollist", - "from", "where_opt", "groupby_opt", "having_opt", - "orderby_opt", "limit_opt", "sclp", "as", + "PRAGMA", "RAISE", "RECURSIVE", "REPLACE", + "RESTRICT", "ROW", "TRIGGER", "VACUUM", + "VIEW", "VIRTUAL", "WITH", "REINDEX", + "RENAME", "CTIME_KW", "ANY", "OR", + "AND", "IS", "BETWEEN", "IN", + "ISNULL", "NOTNULL", "NE", "EQ", + "GT", "LE", "LT", "GE", + "ESCAPE", "BITAND", "BITOR", "LSHIFT", + "RSHIFT", "PLUS", "MINUS", "STAR", + "SLASH", "REM", "CONCAT", "COLLATE", + "BITNOT", "STRING", "JOIN_KW", "CONSTRAINT", + "DEFAULT", "NULL", "PRIMARY", "UNIQUE", + "CHECK", "REFERENCES", "AUTOINCR", "ON", + "INSERT", "DELETE", "UPDATE", "SET", + "DEFERRABLE", "FOREIGN", "DROP", "UNION", + "ALL", "EXCEPT", "INTERSECT", "SELECT", + "VALUES", "DISTINCT", "DOT", "FROM", + "JOIN", "USING", "ORDER", "GROUP", + "HAVING", "LIMIT", "WHERE", "INTO", + "INTEGER", "FLOAT", "BLOB", "VARIABLE", + "CASE", "WHEN", "THEN", "ELSE", + "INDEX", "ALTER", "ADD", "error", + "input", "cmdlist", "ecmd", "explain", + "cmdx", "cmd", "transtype", "trans_opt", + "nm", "savepoint_opt", "create_table", "create_table_args", + "createkw", "temp", "ifnotexists", "dbnm", + "columnlist", "conslist_opt", "table_options", "select", + "column", "columnid", "type", "carglist", + "typetoken", "typename", "signed", "plus_num", + "minus_num", "ccons", "term", "expr", + "onconf", "sortorder", "autoinc", "idxlist_opt", + "refargs", "defer_subclause", "refarg", "refact", + "init_deferred_pred_opt", "conslist", "tconscomma", "tcons", + "idxlist", "defer_subclause_opt", "orconf", "resolvetype", + "raisetype", "ifexists", "fullname", "selectnowith", + "oneselect", "with", "multiselect_op", "distinct", + "selcollist", "from", "where_opt", "groupby_opt", + "having_opt", "orderby_opt", "limit_opt", "values", + "nexprlist", "exprlist", "sclp", "as", "seltablist", "stl_prefix", "joinop", "indexed_opt", "on_opt", "using_opt", "joinop2", "idlist", - "sortlist", "nexprlist", "setlist", "insert_cmd", - "inscollist_opt", "valuelist", "exprlist", "likeop", - "between_op", "in_op", "case_operand", "case_exprlist", - "case_else", "uniqueflag", "collate", "nmnum", - "number", "trigger_decl", "trigger_cmd_list", "trigger_time", + "sortlist", "setlist", "insert_cmd", "inscollist_opt", + "likeop", "between_op", "in_op", "case_operand", + "case_exprlist", "case_else", "uniqueflag", "collate", + "nmnum", "trigger_decl", "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", "when_clause", "trigger_cmd", "trnm", "tridxby", "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", "lp", "anylist", + "wqlist", }; #endif /* NDEBUG */ @@ -115357,295 +116371,293 @@ static const char *const yyRuleName[] = { /* 37 */ "columnlist ::= column", /* 38 */ "column ::= columnid type carglist", /* 39 */ "columnid ::= nm", - /* 40 */ "id ::= ID", - /* 41 */ "id ::= INDEXED", - /* 42 */ "ids ::= ID|STRING", - /* 43 */ "nm ::= id", - /* 44 */ "nm ::= STRING", - /* 45 */ "nm ::= JOIN_KW", - /* 46 */ "type ::=", - /* 47 */ "type ::= typetoken", - /* 48 */ "typetoken ::= typename", - /* 49 */ "typetoken ::= typename LP signed RP", - /* 50 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 51 */ "typename ::= ids", - /* 52 */ "typename ::= typename ids", - /* 53 */ "signed ::= plus_num", - /* 54 */ "signed ::= minus_num", - /* 55 */ "carglist ::= carglist ccons", - /* 56 */ "carglist ::=", - /* 57 */ "ccons ::= CONSTRAINT nm", - /* 58 */ "ccons ::= DEFAULT term", - /* 59 */ "ccons ::= DEFAULT LP expr RP", - /* 60 */ "ccons ::= DEFAULT PLUS term", - /* 61 */ "ccons ::= DEFAULT MINUS term", - /* 62 */ "ccons ::= DEFAULT id", - /* 63 */ "ccons ::= NULL onconf", - /* 64 */ "ccons ::= NOT NULL onconf", - /* 65 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 66 */ "ccons ::= UNIQUE onconf", - /* 67 */ "ccons ::= CHECK LP expr RP", - /* 68 */ "ccons ::= REFERENCES nm idxlist_opt refargs", - /* 69 */ "ccons ::= defer_subclause", - /* 70 */ "ccons ::= COLLATE ids", - /* 71 */ "autoinc ::=", - /* 72 */ "autoinc ::= AUTOINCR", - /* 73 */ "refargs ::=", - /* 74 */ "refargs ::= refargs refarg", - /* 75 */ "refarg ::= MATCH nm", - /* 76 */ "refarg ::= ON INSERT refact", - /* 77 */ "refarg ::= ON DELETE refact", - /* 78 */ "refarg ::= ON UPDATE refact", - /* 79 */ "refact ::= SET NULL", - /* 80 */ "refact ::= SET DEFAULT", - /* 81 */ "refact ::= CASCADE", - /* 82 */ "refact ::= RESTRICT", - /* 83 */ "refact ::= NO ACTION", - /* 84 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 85 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 86 */ "init_deferred_pred_opt ::=", - /* 87 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 88 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 89 */ "conslist_opt ::=", - /* 90 */ "conslist_opt ::= COMMA conslist", - /* 91 */ "conslist ::= conslist tconscomma tcons", - /* 92 */ "conslist ::= tcons", - /* 93 */ "tconscomma ::= COMMA", - /* 94 */ "tconscomma ::=", - /* 95 */ "tcons ::= CONSTRAINT nm", - /* 96 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", - /* 97 */ "tcons ::= UNIQUE LP idxlist RP onconf", - /* 98 */ "tcons ::= CHECK LP expr RP onconf", - /* 99 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", - /* 100 */ "defer_subclause_opt ::=", - /* 101 */ "defer_subclause_opt ::= defer_subclause", - /* 102 */ "onconf ::=", - /* 103 */ "onconf ::= ON CONFLICT resolvetype", - /* 104 */ "orconf ::=", - /* 105 */ "orconf ::= OR resolvetype", - /* 106 */ "resolvetype ::= raisetype", - /* 107 */ "resolvetype ::= IGNORE", - /* 108 */ "resolvetype ::= REPLACE", - /* 109 */ "cmd ::= DROP TABLE ifexists fullname", - /* 110 */ "ifexists ::= IF EXISTS", - /* 111 */ "ifexists ::=", - /* 112 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select", - /* 113 */ "cmd ::= DROP VIEW ifexists fullname", - /* 114 */ "cmd ::= select", - /* 115 */ "select ::= oneselect", - /* 116 */ "select ::= select multiselect_op oneselect", - /* 117 */ "multiselect_op ::= UNION", - /* 118 */ "multiselect_op ::= UNION ALL", - /* 119 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 120 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 121 */ "distinct ::= DISTINCT", - /* 122 */ "distinct ::= ALL", - /* 123 */ "distinct ::=", - /* 124 */ "sclp ::= selcollist COMMA", - /* 125 */ "sclp ::=", - /* 126 */ "selcollist ::= sclp expr as", - /* 127 */ "selcollist ::= sclp STAR", - /* 128 */ "selcollist ::= sclp nm DOT STAR", - /* 129 */ "as ::= AS nm", - /* 130 */ "as ::= ids", - /* 131 */ "as ::=", - /* 132 */ "from ::=", - /* 133 */ "from ::= FROM seltablist", - /* 134 */ "stl_prefix ::= seltablist joinop", - /* 135 */ "stl_prefix ::=", - /* 136 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 137 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 138 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 139 */ "dbnm ::=", - /* 140 */ "dbnm ::= DOT nm", - /* 141 */ "fullname ::= nm dbnm", - /* 142 */ "joinop ::= COMMA|JOIN", - /* 143 */ "joinop ::= JOIN_KW JOIN", - /* 144 */ "joinop ::= JOIN_KW nm JOIN", - /* 145 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 146 */ "on_opt ::= ON expr", - /* 147 */ "on_opt ::=", - /* 148 */ "indexed_opt ::=", - /* 149 */ "indexed_opt ::= INDEXED BY nm", - /* 150 */ "indexed_opt ::= NOT INDEXED", - /* 151 */ "using_opt ::= USING LP idlist RP", - /* 152 */ "using_opt ::=", - /* 153 */ "orderby_opt ::=", - /* 154 */ "orderby_opt ::= ORDER BY sortlist", - /* 155 */ "sortlist ::= sortlist COMMA expr sortorder", - /* 156 */ "sortlist ::= expr sortorder", - /* 157 */ "sortorder ::= ASC", - /* 158 */ "sortorder ::= DESC", - /* 159 */ "sortorder ::=", - /* 160 */ "groupby_opt ::=", - /* 161 */ "groupby_opt ::= GROUP BY nexprlist", - /* 162 */ "having_opt ::=", - /* 163 */ "having_opt ::= HAVING expr", - /* 164 */ "limit_opt ::=", - /* 165 */ "limit_opt ::= LIMIT expr", - /* 166 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 167 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 168 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt", - /* 169 */ "where_opt ::=", - /* 170 */ "where_opt ::= WHERE expr", - /* 171 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt", - /* 172 */ "setlist ::= setlist COMMA nm EQ expr", - /* 173 */ "setlist ::= nm EQ expr", - /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist", - /* 175 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", - /* 176 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES", + /* 40 */ "nm ::= ID|INDEXED", + /* 41 */ "nm ::= STRING", + /* 42 */ "nm ::= JOIN_KW", + /* 43 */ "type ::=", + /* 44 */ "type ::= typetoken", + /* 45 */ "typetoken ::= typename", + /* 46 */ "typetoken ::= typename LP signed RP", + /* 47 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 48 */ "typename ::= ID|STRING", + /* 49 */ "typename ::= typename ID|STRING", + /* 50 */ "signed ::= plus_num", + /* 51 */ "signed ::= minus_num", + /* 52 */ "carglist ::= carglist ccons", + /* 53 */ "carglist ::=", + /* 54 */ "ccons ::= CONSTRAINT nm", + /* 55 */ "ccons ::= DEFAULT term", + /* 56 */ "ccons ::= DEFAULT LP expr RP", + /* 57 */ "ccons ::= DEFAULT PLUS term", + /* 58 */ "ccons ::= DEFAULT MINUS term", + /* 59 */ "ccons ::= DEFAULT ID|INDEXED", + /* 60 */ "ccons ::= NULL onconf", + /* 61 */ "ccons ::= NOT NULL onconf", + /* 62 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 63 */ "ccons ::= UNIQUE onconf", + /* 64 */ "ccons ::= CHECK LP expr RP", + /* 65 */ "ccons ::= REFERENCES nm idxlist_opt refargs", + /* 66 */ "ccons ::= defer_subclause", + /* 67 */ "ccons ::= COLLATE ID|STRING", + /* 68 */ "autoinc ::=", + /* 69 */ "autoinc ::= AUTOINCR", + /* 70 */ "refargs ::=", + /* 71 */ "refargs ::= refargs refarg", + /* 72 */ "refarg ::= MATCH nm", + /* 73 */ "refarg ::= ON INSERT refact", + /* 74 */ "refarg ::= ON DELETE refact", + /* 75 */ "refarg ::= ON UPDATE refact", + /* 76 */ "refact ::= SET NULL", + /* 77 */ "refact ::= SET DEFAULT", + /* 78 */ "refact ::= CASCADE", + /* 79 */ "refact ::= RESTRICT", + /* 80 */ "refact ::= NO ACTION", + /* 81 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 82 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 83 */ "init_deferred_pred_opt ::=", + /* 84 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 85 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 86 */ "conslist_opt ::=", + /* 87 */ "conslist_opt ::= COMMA conslist", + /* 88 */ "conslist ::= conslist tconscomma tcons", + /* 89 */ "conslist ::= tcons", + /* 90 */ "tconscomma ::= COMMA", + /* 91 */ "tconscomma ::=", + /* 92 */ "tcons ::= CONSTRAINT nm", + /* 93 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", + /* 94 */ "tcons ::= UNIQUE LP idxlist RP onconf", + /* 95 */ "tcons ::= CHECK LP expr RP onconf", + /* 96 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", + /* 97 */ "defer_subclause_opt ::=", + /* 98 */ "defer_subclause_opt ::= defer_subclause", + /* 99 */ "onconf ::=", + /* 100 */ "onconf ::= ON CONFLICT resolvetype", + /* 101 */ "orconf ::=", + /* 102 */ "orconf ::= OR resolvetype", + /* 103 */ "resolvetype ::= raisetype", + /* 104 */ "resolvetype ::= IGNORE", + /* 105 */ "resolvetype ::= REPLACE", + /* 106 */ "cmd ::= DROP TABLE ifexists fullname", + /* 107 */ "ifexists ::= IF EXISTS", + /* 108 */ "ifexists ::=", + /* 109 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select", + /* 110 */ "cmd ::= DROP VIEW ifexists fullname", + /* 111 */ "cmd ::= select", + /* 112 */ "select ::= with selectnowith", + /* 113 */ "selectnowith ::= oneselect", + /* 114 */ "selectnowith ::= selectnowith multiselect_op oneselect", + /* 115 */ "multiselect_op ::= UNION", + /* 116 */ "multiselect_op ::= UNION ALL", + /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 119 */ "oneselect ::= values", + /* 120 */ "values ::= VALUES LP nexprlist RP", + /* 121 */ "values ::= values COMMA LP exprlist RP", + /* 122 */ "distinct ::= DISTINCT", + /* 123 */ "distinct ::= ALL", + /* 124 */ "distinct ::=", + /* 125 */ "sclp ::= selcollist COMMA", + /* 126 */ "sclp ::=", + /* 127 */ "selcollist ::= sclp expr as", + /* 128 */ "selcollist ::= sclp STAR", + /* 129 */ "selcollist ::= sclp nm DOT STAR", + /* 130 */ "as ::= AS nm", + /* 131 */ "as ::= ID|STRING", + /* 132 */ "as ::=", + /* 133 */ "from ::=", + /* 134 */ "from ::= FROM seltablist", + /* 135 */ "stl_prefix ::= seltablist joinop", + /* 136 */ "stl_prefix ::=", + /* 137 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", + /* 138 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", + /* 139 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", + /* 140 */ "dbnm ::=", + /* 141 */ "dbnm ::= DOT nm", + /* 142 */ "fullname ::= nm dbnm", + /* 143 */ "joinop ::= COMMA|JOIN", + /* 144 */ "joinop ::= JOIN_KW JOIN", + /* 145 */ "joinop ::= JOIN_KW nm JOIN", + /* 146 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 147 */ "on_opt ::= ON expr", + /* 148 */ "on_opt ::=", + /* 149 */ "indexed_opt ::=", + /* 150 */ "indexed_opt ::= INDEXED BY nm", + /* 151 */ "indexed_opt ::= NOT INDEXED", + /* 152 */ "using_opt ::= USING LP idlist RP", + /* 153 */ "using_opt ::=", + /* 154 */ "orderby_opt ::=", + /* 155 */ "orderby_opt ::= ORDER BY sortlist", + /* 156 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 157 */ "sortlist ::= expr sortorder", + /* 158 */ "sortorder ::= ASC", + /* 159 */ "sortorder ::= DESC", + /* 160 */ "sortorder ::=", + /* 161 */ "groupby_opt ::=", + /* 162 */ "groupby_opt ::= GROUP BY nexprlist", + /* 163 */ "having_opt ::=", + /* 164 */ "having_opt ::= HAVING expr", + /* 165 */ "limit_opt ::=", + /* 166 */ "limit_opt ::= LIMIT expr", + /* 167 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 168 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 169 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", + /* 170 */ "where_opt ::=", + /* 171 */ "where_opt ::= WHERE expr", + /* 172 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", + /* 173 */ "setlist ::= setlist COMMA nm EQ expr", + /* 174 */ "setlist ::= nm EQ expr", + /* 175 */ "cmd ::= with insert_cmd INTO fullname inscollist_opt select", + /* 176 */ "cmd ::= with insert_cmd INTO fullname inscollist_opt DEFAULT VALUES", /* 177 */ "insert_cmd ::= INSERT orconf", /* 178 */ "insert_cmd ::= REPLACE", - /* 179 */ "valuelist ::= VALUES LP nexprlist RP", - /* 180 */ "valuelist ::= valuelist COMMA LP exprlist RP", - /* 181 */ "inscollist_opt ::=", - /* 182 */ "inscollist_opt ::= LP idlist RP", - /* 183 */ "idlist ::= idlist COMMA nm", - /* 184 */ "idlist ::= nm", - /* 185 */ "expr ::= term", - /* 186 */ "expr ::= LP expr RP", - /* 187 */ "term ::= NULL", - /* 188 */ "expr ::= id", - /* 189 */ "expr ::= JOIN_KW", - /* 190 */ "expr ::= nm DOT nm", - /* 191 */ "expr ::= nm DOT nm DOT nm", - /* 192 */ "term ::= INTEGER|FLOAT|BLOB", - /* 193 */ "term ::= STRING", - /* 194 */ "expr ::= REGISTER", - /* 195 */ "expr ::= VARIABLE", - /* 196 */ "expr ::= expr COLLATE ids", - /* 197 */ "expr ::= CAST LP expr AS typetoken RP", - /* 198 */ "expr ::= ID LP distinct exprlist RP", - /* 199 */ "expr ::= ID LP STAR RP", - /* 200 */ "term ::= CTIME_KW", - /* 201 */ "expr ::= expr AND expr", - /* 202 */ "expr ::= expr OR expr", - /* 203 */ "expr ::= expr LT|GT|GE|LE expr", - /* 204 */ "expr ::= expr EQ|NE expr", - /* 205 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 206 */ "expr ::= expr PLUS|MINUS expr", - /* 207 */ "expr ::= expr STAR|SLASH|REM expr", - /* 208 */ "expr ::= expr CONCAT expr", - /* 209 */ "likeop ::= LIKE_KW", - /* 210 */ "likeop ::= NOT LIKE_KW", - /* 211 */ "likeop ::= MATCH", - /* 212 */ "likeop ::= NOT MATCH", - /* 213 */ "expr ::= expr likeop expr", - /* 214 */ "expr ::= expr likeop expr ESCAPE expr", - /* 215 */ "expr ::= expr ISNULL|NOTNULL", - /* 216 */ "expr ::= expr NOT NULL", - /* 217 */ "expr ::= expr IS expr", - /* 218 */ "expr ::= expr IS NOT expr", - /* 219 */ "expr ::= NOT expr", - /* 220 */ "expr ::= BITNOT expr", - /* 221 */ "expr ::= MINUS expr", - /* 222 */ "expr ::= PLUS expr", - /* 223 */ "between_op ::= BETWEEN", - /* 224 */ "between_op ::= NOT BETWEEN", - /* 225 */ "expr ::= expr between_op expr AND expr", - /* 226 */ "in_op ::= IN", - /* 227 */ "in_op ::= NOT IN", - /* 228 */ "expr ::= expr in_op LP exprlist RP", - /* 229 */ "expr ::= LP select RP", - /* 230 */ "expr ::= expr in_op LP select RP", - /* 231 */ "expr ::= expr in_op nm dbnm", - /* 232 */ "expr ::= EXISTS LP select RP", - /* 233 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 234 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 235 */ "case_exprlist ::= WHEN expr THEN expr", - /* 236 */ "case_else ::= ELSE expr", - /* 237 */ "case_else ::=", - /* 238 */ "case_operand ::= expr", - /* 239 */ "case_operand ::=", - /* 240 */ "exprlist ::= nexprlist", - /* 241 */ "exprlist ::=", - /* 242 */ "nexprlist ::= nexprlist COMMA expr", - /* 243 */ "nexprlist ::= expr", - /* 244 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt", - /* 245 */ "uniqueflag ::= UNIQUE", - /* 246 */ "uniqueflag ::=", - /* 247 */ "idxlist_opt ::=", - /* 248 */ "idxlist_opt ::= LP idxlist RP", - /* 249 */ "idxlist ::= idxlist COMMA nm collate sortorder", - /* 250 */ "idxlist ::= nm collate sortorder", - /* 251 */ "collate ::=", - /* 252 */ "collate ::= COLLATE ids", - /* 253 */ "cmd ::= DROP INDEX ifexists fullname", - /* 254 */ "cmd ::= VACUUM", - /* 255 */ "cmd ::= VACUUM nm", - /* 256 */ "cmd ::= PRAGMA nm dbnm", - /* 257 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 258 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 259 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 260 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 261 */ "nmnum ::= plus_num", - /* 262 */ "nmnum ::= nm", - /* 263 */ "nmnum ::= ON", - /* 264 */ "nmnum ::= DELETE", - /* 265 */ "nmnum ::= DEFAULT", - /* 266 */ "plus_num ::= PLUS number", - /* 267 */ "plus_num ::= number", - /* 268 */ "minus_num ::= MINUS number", - /* 269 */ "number ::= INTEGER|FLOAT", - /* 270 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 271 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 272 */ "trigger_time ::= BEFORE", - /* 273 */ "trigger_time ::= AFTER", - /* 274 */ "trigger_time ::= INSTEAD OF", - /* 275 */ "trigger_time ::=", - /* 276 */ "trigger_event ::= DELETE|INSERT", - /* 277 */ "trigger_event ::= UPDATE", - /* 278 */ "trigger_event ::= UPDATE OF idlist", - /* 279 */ "foreach_clause ::=", - /* 280 */ "foreach_clause ::= FOR EACH ROW", - /* 281 */ "when_clause ::=", - /* 282 */ "when_clause ::= WHEN expr", - /* 283 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 284 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 285 */ "trnm ::= nm", - /* 286 */ "trnm ::= nm DOT nm", - /* 287 */ "tridxby ::=", - /* 288 */ "tridxby ::= INDEXED BY nm", - /* 289 */ "tridxby ::= NOT INDEXED", - /* 290 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 291 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist", - /* 292 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", - /* 293 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 294 */ "trigger_cmd ::= select", - /* 295 */ "expr ::= RAISE LP IGNORE RP", - /* 296 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 297 */ "raisetype ::= ROLLBACK", - /* 298 */ "raisetype ::= ABORT", - /* 299 */ "raisetype ::= FAIL", - /* 300 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 301 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 302 */ "cmd ::= DETACH database_kw_opt expr", - /* 303 */ "key_opt ::=", - /* 304 */ "key_opt ::= KEY expr", - /* 305 */ "database_kw_opt ::= DATABASE", - /* 306 */ "database_kw_opt ::=", - /* 307 */ "cmd ::= REINDEX", - /* 308 */ "cmd ::= REINDEX nm dbnm", - /* 309 */ "cmd ::= ANALYZE", - /* 310 */ "cmd ::= ANALYZE nm dbnm", - /* 311 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 312 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 313 */ "add_column_fullname ::= fullname", - /* 314 */ "kwcolumn_opt ::=", - /* 315 */ "kwcolumn_opt ::= COLUMNKW", - /* 316 */ "cmd ::= create_vtab", - /* 317 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 318 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 319 */ "vtabarglist ::= vtabarg", - /* 320 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 321 */ "vtabarg ::=", - /* 322 */ "vtabarg ::= vtabarg vtabargtoken", - /* 323 */ "vtabargtoken ::= ANY", - /* 324 */ "vtabargtoken ::= lp anylist RP", - /* 325 */ "lp ::= LP", - /* 326 */ "anylist ::=", - /* 327 */ "anylist ::= anylist LP anylist RP", - /* 328 */ "anylist ::= anylist ANY", + /* 179 */ "inscollist_opt ::=", + /* 180 */ "inscollist_opt ::= LP idlist RP", + /* 181 */ "idlist ::= idlist COMMA nm", + /* 182 */ "idlist ::= nm", + /* 183 */ "expr ::= term", + /* 184 */ "expr ::= LP expr RP", + /* 185 */ "term ::= NULL", + /* 186 */ "expr ::= ID|INDEXED", + /* 187 */ "expr ::= JOIN_KW", + /* 188 */ "expr ::= nm DOT nm", + /* 189 */ "expr ::= nm DOT nm DOT nm", + /* 190 */ "term ::= INTEGER|FLOAT|BLOB", + /* 191 */ "term ::= STRING", + /* 192 */ "expr ::= VARIABLE", + /* 193 */ "expr ::= expr COLLATE ID|STRING", + /* 194 */ "expr ::= CAST LP expr AS typetoken RP", + /* 195 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 196 */ "expr ::= ID|INDEXED LP STAR RP", + /* 197 */ "term ::= CTIME_KW", + /* 198 */ "expr ::= expr AND expr", + /* 199 */ "expr ::= expr OR expr", + /* 200 */ "expr ::= expr LT|GT|GE|LE expr", + /* 201 */ "expr ::= expr EQ|NE expr", + /* 202 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 203 */ "expr ::= expr PLUS|MINUS expr", + /* 204 */ "expr ::= expr STAR|SLASH|REM expr", + /* 205 */ "expr ::= expr CONCAT expr", + /* 206 */ "likeop ::= LIKE_KW|MATCH", + /* 207 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 208 */ "expr ::= expr likeop expr", + /* 209 */ "expr ::= expr likeop expr ESCAPE expr", + /* 210 */ "expr ::= expr ISNULL|NOTNULL", + /* 211 */ "expr ::= expr NOT NULL", + /* 212 */ "expr ::= expr IS expr", + /* 213 */ "expr ::= expr IS NOT expr", + /* 214 */ "expr ::= NOT expr", + /* 215 */ "expr ::= BITNOT expr", + /* 216 */ "expr ::= MINUS expr", + /* 217 */ "expr ::= PLUS expr", + /* 218 */ "between_op ::= BETWEEN", + /* 219 */ "between_op ::= NOT BETWEEN", + /* 220 */ "expr ::= expr between_op expr AND expr", + /* 221 */ "in_op ::= IN", + /* 222 */ "in_op ::= NOT IN", + /* 223 */ "expr ::= expr in_op LP exprlist RP", + /* 224 */ "expr ::= LP select RP", + /* 225 */ "expr ::= expr in_op LP select RP", + /* 226 */ "expr ::= expr in_op nm dbnm", + /* 227 */ "expr ::= EXISTS LP select RP", + /* 228 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 229 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 230 */ "case_exprlist ::= WHEN expr THEN expr", + /* 231 */ "case_else ::= ELSE expr", + /* 232 */ "case_else ::=", + /* 233 */ "case_operand ::= expr", + /* 234 */ "case_operand ::=", + /* 235 */ "exprlist ::= nexprlist", + /* 236 */ "exprlist ::=", + /* 237 */ "nexprlist ::= nexprlist COMMA expr", + /* 238 */ "nexprlist ::= expr", + /* 239 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt", + /* 240 */ "uniqueflag ::= UNIQUE", + /* 241 */ "uniqueflag ::=", + /* 242 */ "idxlist_opt ::=", + /* 243 */ "idxlist_opt ::= LP idxlist RP", + /* 244 */ "idxlist ::= idxlist COMMA nm collate sortorder", + /* 245 */ "idxlist ::= nm collate sortorder", + /* 246 */ "collate ::=", + /* 247 */ "collate ::= COLLATE ID|STRING", + /* 248 */ "cmd ::= DROP INDEX ifexists fullname", + /* 249 */ "cmd ::= VACUUM", + /* 250 */ "cmd ::= VACUUM nm", + /* 251 */ "cmd ::= PRAGMA nm dbnm", + /* 252 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 255 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 256 */ "nmnum ::= plus_num", + /* 257 */ "nmnum ::= nm", + /* 258 */ "nmnum ::= ON", + /* 259 */ "nmnum ::= DELETE", + /* 260 */ "nmnum ::= DEFAULT", + /* 261 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 262 */ "plus_num ::= INTEGER|FLOAT", + /* 263 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 264 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 265 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 266 */ "trigger_time ::= BEFORE", + /* 267 */ "trigger_time ::= AFTER", + /* 268 */ "trigger_time ::= INSTEAD OF", + /* 269 */ "trigger_time ::=", + /* 270 */ "trigger_event ::= DELETE|INSERT", + /* 271 */ "trigger_event ::= UPDATE", + /* 272 */ "trigger_event ::= UPDATE OF idlist", + /* 273 */ "foreach_clause ::=", + /* 274 */ "foreach_clause ::= FOR EACH ROW", + /* 275 */ "when_clause ::=", + /* 276 */ "when_clause ::= WHEN expr", + /* 277 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 278 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 279 */ "trnm ::= nm", + /* 280 */ "trnm ::= nm DOT nm", + /* 281 */ "tridxby ::=", + /* 282 */ "tridxby ::= INDEXED BY nm", + /* 283 */ "tridxby ::= NOT INDEXED", + /* 284 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 285 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", + /* 286 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 287 */ "trigger_cmd ::= select", + /* 288 */ "expr ::= RAISE LP IGNORE RP", + /* 289 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 290 */ "raisetype ::= ROLLBACK", + /* 291 */ "raisetype ::= ABORT", + /* 292 */ "raisetype ::= FAIL", + /* 293 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 294 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 295 */ "cmd ::= DETACH database_kw_opt expr", + /* 296 */ "key_opt ::=", + /* 297 */ "key_opt ::= KEY expr", + /* 298 */ "database_kw_opt ::= DATABASE", + /* 299 */ "database_kw_opt ::=", + /* 300 */ "cmd ::= REINDEX", + /* 301 */ "cmd ::= REINDEX nm dbnm", + /* 302 */ "cmd ::= ANALYZE", + /* 303 */ "cmd ::= ANALYZE nm dbnm", + /* 304 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 305 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 306 */ "add_column_fullname ::= fullname", + /* 307 */ "kwcolumn_opt ::=", + /* 308 */ "kwcolumn_opt ::= COLUMNKW", + /* 309 */ "cmd ::= create_vtab", + /* 310 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 311 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 312 */ "vtabarglist ::= vtabarg", + /* 313 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 314 */ "vtabarg ::=", + /* 315 */ "vtabarg ::= vtabarg vtabargtoken", + /* 316 */ "vtabargtoken ::= ANY", + /* 317 */ "vtabargtoken ::= lp anylist RP", + /* 318 */ "lp ::= LP", + /* 319 */ "anylist ::=", + /* 320 */ "anylist ::= anylist LP anylist RP", + /* 321 */ "anylist ::= anylist ANY", + /* 322 */ "with ::=", + /* 323 */ "with ::= WITH wqlist", + /* 324 */ "with ::= WITH RECURSIVE wqlist", + /* 325 */ "wqlist ::= nm idxlist_opt AS LP select RP", + /* 326 */ "wqlist ::= wqlist COMMA nm idxlist_opt AS LP select RP", }; #endif /* NDEBUG */ @@ -115724,76 +116736,76 @@ static void yy_destructor( ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ - case 162: /* select */ + case 163: /* select */ + case 195: /* selectnowith */ case 196: /* oneselect */ + case 207: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy387)); +sqlite3SelectDelete(pParse->db, (yypminor->yy3)); } break; - case 175: /* term */ - case 176: /* expr */ + case 174: /* term */ + case 175: /* expr */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy118).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy346).pExpr); } break; - case 180: /* idxlist_opt */ - case 189: /* idxlist */ - case 199: /* selcollist */ - case 202: /* groupby_opt */ - case 204: /* orderby_opt */ - case 206: /* sclp */ - case 216: /* sortlist */ - case 217: /* nexprlist */ - case 218: /* setlist */ - case 222: /* exprlist */ - case 227: /* case_exprlist */ + case 179: /* idxlist_opt */ + case 188: /* idxlist */ + case 200: /* selcollist */ + case 203: /* groupby_opt */ + case 205: /* orderby_opt */ + case 208: /* nexprlist */ + case 209: /* exprlist */ + case 210: /* sclp */ + case 220: /* sortlist */ + case 221: /* setlist */ + case 228: /* case_exprlist */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); } break; - case 195: /* fullname */ - case 200: /* from */ - case 208: /* seltablist */ - case 209: /* stl_prefix */ + case 194: /* fullname */ + case 201: /* from */ + case 212: /* seltablist */ + case 213: /* stl_prefix */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy259)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy65)); } break; - case 201: /* where_opt */ - case 203: /* having_opt */ - case 212: /* on_opt */ - case 226: /* case_operand */ - case 228: /* case_else */ - case 238: /* when_clause */ - case 243: /* key_opt */ + case 197: /* with */ + case 252: /* wqlist */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy314)); +sqlite3WithDelete(pParse->db, (yypminor->yy59)); } break; - case 213: /* using_opt */ - case 215: /* idlist */ - case 220: /* inscollist_opt */ + case 202: /* where_opt */ + case 204: /* having_opt */ + case 216: /* on_opt */ + case 227: /* case_operand */ + case 229: /* case_else */ + case 238: /* when_clause */ + case 243: /* key_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy384)); +sqlite3ExprDelete(pParse->db, (yypminor->yy132)); } break; - case 221: /* valuelist */ + case 217: /* using_opt */ + case 219: /* idlist */ + case 223: /* inscollist_opt */ { - - sqlite3ExprListDelete(pParse->db, (yypminor->yy260).pList); - sqlite3SelectDelete(pParse->db, (yypminor->yy260).pSelect); - +sqlite3IdListDelete(pParse->db, (yypminor->yy408)); } break; case 234: /* trigger_cmd_list */ case 239: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy473)); } break; case 236: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy378).b); } break; default: break; /* If no destructor action specified: do nothing */ @@ -116038,277 +117050,271 @@ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { - { 143, 1 }, - { 144, 2 }, { 144, 1 }, + { 145, 2 }, { 145, 1 }, - { 145, 3 }, - { 146, 0 }, { 146, 1 }, { 146, 3 }, + { 147, 0 }, { 147, 1 }, - { 148, 3 }, + { 147, 3 }, + { 148, 1 }, + { 149, 3 }, + { 151, 0 }, + { 151, 1 }, + { 151, 2 }, { 150, 0 }, { 150, 1 }, - { 150, 2 }, - { 149, 0 }, - { 149, 1 }, - { 149, 1 }, - { 149, 1 }, - { 148, 2 }, - { 148, 2 }, - { 148, 2 }, - { 152, 1 }, - { 152, 0 }, - { 148, 2 }, - { 148, 3 }, - { 148, 5 }, - { 148, 2 }, - { 153, 6 }, - { 155, 1 }, - { 157, 0 }, - { 157, 3 }, + { 150, 1 }, + { 150, 1 }, + { 149, 2 }, + { 149, 2 }, + { 149, 2 }, + { 153, 1 }, + { 153, 0 }, + { 149, 2 }, + { 149, 3 }, + { 149, 5 }, + { 149, 2 }, + { 154, 6 }, { 156, 1 }, - { 156, 0 }, - { 154, 5 }, - { 154, 2 }, - { 161, 0 }, - { 161, 2 }, - { 159, 3 }, - { 159, 1 }, - { 163, 3 }, - { 164, 1 }, - { 167, 1 }, - { 167, 1 }, - { 168, 1 }, - { 151, 1 }, - { 151, 1 }, - { 151, 1 }, - { 165, 0 }, + { 158, 0 }, + { 158, 3 }, + { 157, 1 }, + { 157, 0 }, + { 155, 5 }, + { 155, 2 }, + { 162, 0 }, + { 162, 2 }, + { 160, 3 }, + { 160, 1 }, + { 164, 3 }, { 165, 1 }, + { 152, 1 }, + { 152, 1 }, + { 152, 1 }, + { 166, 0 }, + { 166, 1 }, + { 168, 1 }, + { 168, 4 }, + { 168, 6 }, { 169, 1 }, - { 169, 4 }, - { 169, 6 }, + { 169, 2 }, { 170, 1 }, - { 170, 2 }, - { 171, 1 }, - { 171, 1 }, - { 166, 2 }, - { 166, 0 }, - { 174, 2 }, - { 174, 2 }, - { 174, 4 }, - { 174, 3 }, - { 174, 3 }, - { 174, 2 }, - { 174, 2 }, - { 174, 3 }, - { 174, 5 }, - { 174, 2 }, - { 174, 4 }, - { 174, 4 }, - { 174, 1 }, - { 174, 2 }, - { 179, 0 }, - { 179, 1 }, - { 181, 0 }, - { 181, 2 }, + { 170, 1 }, + { 167, 2 }, + { 167, 0 }, + { 173, 2 }, + { 173, 2 }, + { 173, 4 }, + { 173, 3 }, + { 173, 3 }, + { 173, 2 }, + { 173, 2 }, + { 173, 3 }, + { 173, 5 }, + { 173, 2 }, + { 173, 4 }, + { 173, 4 }, + { 173, 1 }, + { 173, 2 }, + { 178, 0 }, + { 178, 1 }, + { 180, 0 }, + { 180, 2 }, + { 182, 2 }, + { 182, 3 }, + { 182, 3 }, + { 182, 3 }, { 183, 2 }, - { 183, 3 }, - { 183, 3 }, - { 183, 3 }, - { 184, 2 }, + { 183, 2 }, + { 183, 1 }, + { 183, 1 }, + { 183, 2 }, + { 181, 3 }, + { 181, 2 }, + { 184, 0 }, { 184, 2 }, - { 184, 1 }, - { 184, 1 }, { 184, 2 }, - { 182, 3 }, - { 182, 2 }, - { 185, 0 }, - { 185, 2 }, - { 185, 2 }, - { 160, 0 }, - { 160, 2 }, - { 186, 3 }, + { 161, 0 }, + { 161, 2 }, + { 185, 3 }, + { 185, 1 }, { 186, 1 }, - { 187, 1 }, - { 187, 0 }, - { 188, 2 }, - { 188, 7 }, - { 188, 5 }, - { 188, 5 }, - { 188, 10 }, + { 186, 0 }, + { 187, 2 }, + { 187, 7 }, + { 187, 5 }, + { 187, 5 }, + { 187, 10 }, + { 189, 0 }, + { 189, 1 }, + { 176, 0 }, + { 176, 3 }, { 190, 0 }, - { 190, 1 }, - { 177, 0 }, - { 177, 3 }, - { 191, 0 }, - { 191, 2 }, - { 192, 1 }, - { 192, 1 }, - { 192, 1 }, - { 148, 4 }, - { 194, 2 }, - { 194, 0 }, - { 148, 8 }, - { 148, 4 }, - { 148, 1 }, - { 162, 1 }, - { 162, 3 }, - { 197, 1 }, - { 197, 2 }, - { 197, 1 }, - { 196, 9 }, + { 190, 2 }, + { 191, 1 }, + { 191, 1 }, + { 191, 1 }, + { 149, 4 }, + { 193, 2 }, + { 193, 0 }, + { 149, 8 }, + { 149, 4 }, + { 149, 1 }, + { 163, 2 }, + { 195, 1 }, + { 195, 3 }, { 198, 1 }, + { 198, 2 }, { 198, 1 }, - { 198, 0 }, - { 206, 2 }, - { 206, 0 }, - { 199, 3 }, - { 199, 2 }, - { 199, 4 }, - { 207, 2 }, - { 207, 1 }, - { 207, 0 }, - { 200, 0 }, - { 200, 2 }, - { 209, 2 }, - { 209, 0 }, - { 208, 7 }, - { 208, 7 }, - { 208, 7 }, - { 158, 0 }, - { 158, 2 }, - { 195, 2 }, - { 210, 1 }, + { 196, 9 }, + { 196, 1 }, + { 207, 4 }, + { 207, 5 }, + { 199, 1 }, + { 199, 1 }, + { 199, 0 }, { 210, 2 }, - { 210, 3 }, - { 210, 4 }, - { 212, 2 }, - { 212, 0 }, - { 211, 0 }, - { 211, 3 }, + { 210, 0 }, + { 200, 3 }, + { 200, 2 }, + { 200, 4 }, { 211, 2 }, - { 213, 4 }, + { 211, 1 }, + { 211, 0 }, + { 201, 0 }, + { 201, 2 }, + { 213, 2 }, { 213, 0 }, - { 204, 0 }, - { 204, 3 }, - { 216, 4 }, + { 212, 7 }, + { 212, 7 }, + { 212, 7 }, + { 159, 0 }, + { 159, 2 }, + { 194, 2 }, + { 214, 1 }, + { 214, 2 }, + { 214, 3 }, + { 214, 4 }, { 216, 2 }, - { 178, 1 }, - { 178, 1 }, - { 178, 0 }, - { 202, 0 }, - { 202, 3 }, - { 203, 0 }, - { 203, 2 }, + { 216, 0 }, + { 215, 0 }, + { 215, 3 }, + { 215, 2 }, + { 217, 4 }, + { 217, 0 }, { 205, 0 }, - { 205, 2 }, - { 205, 4 }, - { 205, 4 }, - { 148, 5 }, - { 201, 0 }, - { 201, 2 }, - { 148, 7 }, - { 218, 5 }, - { 218, 3 }, - { 148, 5 }, - { 148, 5 }, - { 148, 6 }, - { 219, 2 }, - { 219, 1 }, - { 221, 4 }, + { 205, 3 }, + { 220, 4 }, + { 220, 2 }, + { 177, 1 }, + { 177, 1 }, + { 177, 0 }, + { 203, 0 }, + { 203, 3 }, + { 204, 0 }, + { 204, 2 }, + { 206, 0 }, + { 206, 2 }, + { 206, 4 }, + { 206, 4 }, + { 149, 6 }, + { 202, 0 }, + { 202, 2 }, + { 149, 8 }, { 221, 5 }, - { 220, 0 }, - { 220, 3 }, - { 215, 3 }, - { 215, 1 }, - { 176, 1 }, - { 176, 3 }, + { 221, 3 }, + { 149, 6 }, + { 149, 7 }, + { 222, 2 }, + { 222, 1 }, + { 223, 0 }, + { 223, 3 }, + { 219, 3 }, + { 219, 1 }, { 175, 1 }, - { 176, 1 }, - { 176, 1 }, - { 176, 3 }, - { 176, 5 }, + { 175, 3 }, + { 174, 1 }, { 175, 1 }, { 175, 1 }, - { 176, 1 }, - { 176, 1 }, - { 176, 3 }, - { 176, 6 }, - { 176, 5 }, - { 176, 4 }, + { 175, 3 }, + { 175, 5 }, + { 174, 1 }, + { 174, 1 }, { 175, 1 }, - { 176, 3 }, - { 176, 3 }, - { 176, 3 }, - { 176, 3 }, - { 176, 3 }, - { 176, 3 }, - { 176, 3 }, - { 176, 3 }, - { 223, 1 }, - { 223, 2 }, - { 223, 1 }, - { 223, 2 }, - { 176, 3 }, - { 176, 5 }, - { 176, 2 }, - { 176, 3 }, - { 176, 3 }, - { 176, 4 }, - { 176, 2 }, - { 176, 2 }, - { 176, 2 }, - { 176, 2 }, + { 175, 3 }, + { 175, 6 }, + { 175, 5 }, + { 175, 4 }, + { 174, 1 }, + { 175, 3 }, + { 175, 3 }, + { 175, 3 }, + { 175, 3 }, + { 175, 3 }, + { 175, 3 }, + { 175, 3 }, + { 175, 3 }, { 224, 1 }, { 224, 2 }, - { 176, 5 }, + { 175, 3 }, + { 175, 5 }, + { 175, 2 }, + { 175, 3 }, + { 175, 3 }, + { 175, 4 }, + { 175, 2 }, + { 175, 2 }, + { 175, 2 }, + { 175, 2 }, { 225, 1 }, { 225, 2 }, - { 176, 5 }, - { 176, 3 }, - { 176, 5 }, - { 176, 4 }, - { 176, 4 }, - { 176, 5 }, - { 227, 5 }, - { 227, 4 }, - { 228, 2 }, - { 228, 0 }, + { 175, 5 }, { 226, 1 }, - { 226, 0 }, - { 222, 1 }, - { 222, 0 }, - { 217, 3 }, - { 217, 1 }, - { 148, 12 }, - { 229, 1 }, + { 226, 2 }, + { 175, 5 }, + { 175, 3 }, + { 175, 5 }, + { 175, 4 }, + { 175, 4 }, + { 175, 5 }, + { 228, 5 }, + { 228, 4 }, + { 229, 2 }, { 229, 0 }, - { 180, 0 }, - { 180, 3 }, - { 189, 5 }, - { 189, 3 }, + { 227, 1 }, + { 227, 0 }, + { 209, 1 }, + { 209, 0 }, + { 208, 3 }, + { 208, 1 }, + { 149, 12 }, + { 230, 1 }, { 230, 0 }, - { 230, 2 }, - { 148, 4 }, - { 148, 1 }, - { 148, 2 }, - { 148, 3 }, - { 148, 5 }, - { 148, 6 }, - { 148, 5 }, - { 148, 6 }, - { 231, 1 }, - { 231, 1 }, - { 231, 1 }, - { 231, 1 }, - { 231, 1 }, - { 172, 2 }, - { 172, 1 }, - { 173, 2 }, + { 179, 0 }, + { 179, 3 }, + { 188, 5 }, + { 188, 3 }, + { 231, 0 }, + { 231, 2 }, + { 149, 4 }, + { 149, 1 }, + { 149, 2 }, + { 149, 3 }, + { 149, 5 }, + { 149, 6 }, + { 149, 5 }, + { 149, 6 }, + { 232, 1 }, { 232, 1 }, - { 148, 5 }, + { 232, 1 }, + { 232, 1 }, + { 232, 1 }, + { 171, 2 }, + { 171, 1 }, + { 172, 2 }, + { 149, 5 }, { 233, 11 }, { 235, 1 }, { 235, 1 }, @@ -116331,31 +117337,30 @@ static const struct { { 239, 7 }, { 239, 5 }, { 239, 5 }, - { 239, 5 }, { 239, 1 }, - { 176, 4 }, - { 176, 6 }, - { 193, 1 }, - { 193, 1 }, - { 193, 1 }, - { 148, 4 }, - { 148, 6 }, - { 148, 3 }, + { 175, 4 }, + { 175, 6 }, + { 192, 1 }, + { 192, 1 }, + { 192, 1 }, + { 149, 4 }, + { 149, 6 }, + { 149, 3 }, { 243, 0 }, { 243, 2 }, { 242, 1 }, { 242, 0 }, - { 148, 1 }, - { 148, 3 }, - { 148, 1 }, - { 148, 3 }, - { 148, 6 }, - { 148, 6 }, + { 149, 1 }, + { 149, 3 }, + { 149, 1 }, + { 149, 3 }, + { 149, 6 }, + { 149, 6 }, { 244, 1 }, { 245, 0 }, { 245, 1 }, - { 148, 1 }, - { 148, 4 }, + { 149, 1 }, + { 149, 4 }, { 246, 8 }, { 247, 1 }, { 247, 3 }, @@ -116367,6 +117372,11 @@ static const struct { { 251, 0 }, { 251, 4 }, { 251, 2 }, + { 197, 0 }, + { 197, 2 }, + { 197, 3 }, + { 252, 6 }, + { 252, 8 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -116434,17 +117444,17 @@ static void yy_reduce( { sqlite3FinishCoding(pParse); } break; case 9: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy4);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy328);} break; case 13: /* transtype ::= */ -{yygotominor.yy4 = TK_DEFERRED;} +{yygotominor.yy328 = TK_DEFERRED;} break; case 14: /* transtype ::= DEFERRED */ case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15); case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16); - case 117: /* multiselect_op ::= UNION */ yytestcase(yyruleno==117); - case 119: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==119); -{yygotominor.yy4 = yymsp[0].major;} + case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115); + case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117); +{yygotominor.yy328 = yymsp[0].major;} break; case 17: /* cmd ::= COMMIT trans_opt */ case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18); @@ -116470,7 +117480,7 @@ static void yy_reduce( break; case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy328,0,0,yymsp[-2].minor.yy328); } break; case 27: /* createkw ::= CREATE */ @@ -116481,45 +117491,45 @@ static void yy_reduce( break; case 28: /* ifnotexists ::= */ case 31: /* temp ::= */ yytestcase(yyruleno==31); - case 71: /* autoinc ::= */ yytestcase(yyruleno==71); - case 84: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==84); - case 86: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==86); - case 88: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==88); - case 100: /* defer_subclause_opt ::= */ yytestcase(yyruleno==100); - case 111: /* ifexists ::= */ yytestcase(yyruleno==111); - case 223: /* between_op ::= BETWEEN */ yytestcase(yyruleno==223); - case 226: /* in_op ::= IN */ yytestcase(yyruleno==226); -{yygotominor.yy4 = 0;} + case 68: /* autoinc ::= */ yytestcase(yyruleno==68); + case 81: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==81); + case 83: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==83); + case 85: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==85); + case 97: /* defer_subclause_opt ::= */ yytestcase(yyruleno==97); + case 108: /* ifexists ::= */ yytestcase(yyruleno==108); + case 218: /* between_op ::= BETWEEN */ yytestcase(yyruleno==218); + case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); +{yygotominor.yy328 = 0;} break; case 29: /* ifnotexists ::= IF NOT EXISTS */ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); - case 72: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==72); - case 87: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==87); - case 110: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==110); - case 224: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==224); - case 227: /* in_op ::= NOT IN */ yytestcase(yyruleno==227); -{yygotominor.yy4 = 1;} + case 69: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==69); + case 84: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==84); + case 107: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==107); + case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); + case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); +{yygotominor.yy328 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy210,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy186,0); } break; case 33: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy387); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy3); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3); } break; case 34: /* table_options ::= */ -{yygotominor.yy210 = 0;} +{yygotominor.yy186 = 0;} break; case 35: /* table_options ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yygotominor.yy210 = TF_WithoutRowid; + yygotominor.yy186 = TF_WithoutRowid; }else{ - yygotominor.yy210 = 0; + yygotominor.yy186 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -116537,650 +117547,669 @@ static void yy_reduce( pParse->constraintName.n = 0; } break; - case 40: /* id ::= ID */ - case 41: /* id ::= INDEXED */ yytestcase(yyruleno==41); - case 42: /* ids ::= ID|STRING */ yytestcase(yyruleno==42); - case 43: /* nm ::= id */ yytestcase(yyruleno==43); - case 44: /* nm ::= STRING */ yytestcase(yyruleno==44); - case 45: /* nm ::= JOIN_KW */ yytestcase(yyruleno==45); - case 48: /* typetoken ::= typename */ yytestcase(yyruleno==48); - case 51: /* typename ::= ids */ yytestcase(yyruleno==51); - case 129: /* as ::= AS nm */ yytestcase(yyruleno==129); - case 130: /* as ::= ids */ yytestcase(yyruleno==130); - case 140: /* dbnm ::= DOT nm */ yytestcase(yyruleno==140); - case 149: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==149); - case 252: /* collate ::= COLLATE ids */ yytestcase(yyruleno==252); - case 261: /* nmnum ::= plus_num */ yytestcase(yyruleno==261); - case 262: /* nmnum ::= nm */ yytestcase(yyruleno==262); - case 263: /* nmnum ::= ON */ yytestcase(yyruleno==263); - case 264: /* nmnum ::= DELETE */ yytestcase(yyruleno==264); - case 265: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==265); - case 266: /* plus_num ::= PLUS number */ yytestcase(yyruleno==266); - case 267: /* plus_num ::= number */ yytestcase(yyruleno==267); - case 268: /* minus_num ::= MINUS number */ yytestcase(yyruleno==268); - case 269: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==269); - case 285: /* trnm ::= nm */ yytestcase(yyruleno==285); + case 40: /* nm ::= ID|INDEXED */ + case 41: /* nm ::= STRING */ yytestcase(yyruleno==41); + case 42: /* nm ::= JOIN_KW */ yytestcase(yyruleno==42); + case 45: /* typetoken ::= typename */ yytestcase(yyruleno==45); + case 48: /* typename ::= ID|STRING */ yytestcase(yyruleno==48); + case 130: /* as ::= AS nm */ yytestcase(yyruleno==130); + case 131: /* as ::= ID|STRING */ yytestcase(yyruleno==131); + case 141: /* dbnm ::= DOT nm */ yytestcase(yyruleno==141); + case 150: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==150); + case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); + case 256: /* nmnum ::= plus_num */ yytestcase(yyruleno==256); + case 257: /* nmnum ::= nm */ yytestcase(yyruleno==257); + case 258: /* nmnum ::= ON */ yytestcase(yyruleno==258); + case 259: /* nmnum ::= DELETE */ yytestcase(yyruleno==259); + case 260: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==260); + case 261: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==261); + case 262: /* plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==262); + case 263: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==263); + case 279: /* trnm ::= nm */ yytestcase(yyruleno==279); {yygotominor.yy0 = yymsp[0].minor.yy0;} break; - case 47: /* type ::= typetoken */ + case 44: /* type ::= typetoken */ {sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);} break; - case 49: /* typetoken ::= typename LP signed RP */ + case 46: /* typetoken ::= typename LP signed RP */ { yygotominor.yy0.z = yymsp[-3].minor.yy0.z; yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z); } break; - case 50: /* typetoken ::= typename LP signed COMMA signed RP */ + case 47: /* typetoken ::= typename LP signed COMMA signed RP */ { yygotominor.yy0.z = yymsp[-5].minor.yy0.z; yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z); } break; - case 52: /* typename ::= typename ids */ + case 49: /* typename ::= typename ID|STRING */ {yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} break; - case 57: /* ccons ::= CONSTRAINT nm */ - case 95: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==95); + case 54: /* ccons ::= CONSTRAINT nm */ + case 92: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==92); {pParse->constraintName = yymsp[0].minor.yy0;} break; - case 58: /* ccons ::= DEFAULT term */ - case 60: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==60); -{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy118);} + case 55: /* ccons ::= DEFAULT term */ + case 57: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==57); +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy346);} break; - case 59: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy118);} + case 56: /* ccons ::= DEFAULT LP expr RP */ +{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy346);} break; - case 61: /* ccons ::= DEFAULT MINUS term */ + case 58: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy118.pExpr, 0, 0); + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy346.pExpr, 0, 0); v.zStart = yymsp[-1].minor.yy0.z; - v.zEnd = yymsp[0].minor.yy118.zEnd; + v.zEnd = yymsp[0].minor.yy346.zEnd; sqlite3AddDefaultValue(pParse,&v); } break; - case 62: /* ccons ::= DEFAULT id */ + case 59: /* ccons ::= DEFAULT ID|INDEXED */ { ExprSpan v; spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0); sqlite3AddDefaultValue(pParse,&v); } break; - case 64: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy4);} + case 61: /* ccons ::= NOT NULL onconf */ +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy328);} break; - case 65: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy4,yymsp[0].minor.yy4,yymsp[-2].minor.yy4);} + case 62: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy328,yymsp[0].minor.yy328,yymsp[-2].minor.yy328);} break; - case 66: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy4,0,0,0,0);} + case 63: /* ccons ::= UNIQUE onconf */ +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy328,0,0,0,0);} break; - case 67: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy118.pExpr);} + case 64: /* ccons ::= CHECK LP expr RP */ +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy346.pExpr);} break; - case 68: /* ccons ::= REFERENCES nm idxlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy4);} + case 65: /* ccons ::= REFERENCES nm idxlist_opt refargs */ +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy328);} break; - case 69: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy4);} + case 66: /* ccons ::= defer_subclause */ +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy328);} break; - case 70: /* ccons ::= COLLATE ids */ + case 67: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; - case 73: /* refargs ::= */ -{ yygotominor.yy4 = OE_None*0x0101; /* EV: R-19803-45884 */} + case 70: /* refargs ::= */ +{ yygotominor.yy328 = OE_None*0x0101; /* EV: R-19803-45884 */} break; - case 74: /* refargs ::= refargs refarg */ -{ yygotominor.yy4 = (yymsp[-1].minor.yy4 & ~yymsp[0].minor.yy215.mask) | yymsp[0].minor.yy215.value; } + case 71: /* refargs ::= refargs refarg */ +{ yygotominor.yy328 = (yymsp[-1].minor.yy328 & ~yymsp[0].minor.yy429.mask) | yymsp[0].minor.yy429.value; } break; - case 75: /* refarg ::= MATCH nm */ - case 76: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==76); -{ yygotominor.yy215.value = 0; yygotominor.yy215.mask = 0x000000; } + case 72: /* refarg ::= MATCH nm */ + case 73: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==73); +{ yygotominor.yy429.value = 0; yygotominor.yy429.mask = 0x000000; } break; - case 77: /* refarg ::= ON DELETE refact */ -{ yygotominor.yy215.value = yymsp[0].minor.yy4; yygotominor.yy215.mask = 0x0000ff; } + case 74: /* refarg ::= ON DELETE refact */ +{ yygotominor.yy429.value = yymsp[0].minor.yy328; yygotominor.yy429.mask = 0x0000ff; } break; - case 78: /* refarg ::= ON UPDATE refact */ -{ yygotominor.yy215.value = yymsp[0].minor.yy4<<8; yygotominor.yy215.mask = 0x00ff00; } + case 75: /* refarg ::= ON UPDATE refact */ +{ yygotominor.yy429.value = yymsp[0].minor.yy328<<8; yygotominor.yy429.mask = 0x00ff00; } break; - case 79: /* refact ::= SET NULL */ -{ yygotominor.yy4 = OE_SetNull; /* EV: R-33326-45252 */} + case 76: /* refact ::= SET NULL */ +{ yygotominor.yy328 = OE_SetNull; /* EV: R-33326-45252 */} break; - case 80: /* refact ::= SET DEFAULT */ -{ yygotominor.yy4 = OE_SetDflt; /* EV: R-33326-45252 */} + case 77: /* refact ::= SET DEFAULT */ +{ yygotominor.yy328 = OE_SetDflt; /* EV: R-33326-45252 */} break; - case 81: /* refact ::= CASCADE */ -{ yygotominor.yy4 = OE_Cascade; /* EV: R-33326-45252 */} + case 78: /* refact ::= CASCADE */ +{ yygotominor.yy328 = OE_Cascade; /* EV: R-33326-45252 */} break; - case 82: /* refact ::= RESTRICT */ -{ yygotominor.yy4 = OE_Restrict; /* EV: R-33326-45252 */} + case 79: /* refact ::= RESTRICT */ +{ yygotominor.yy328 = OE_Restrict; /* EV: R-33326-45252 */} break; - case 83: /* refact ::= NO ACTION */ -{ yygotominor.yy4 = OE_None; /* EV: R-33326-45252 */} + case 80: /* refact ::= NO ACTION */ +{ yygotominor.yy328 = OE_None; /* EV: R-33326-45252 */} break; - case 85: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 101: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==101); - case 103: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==103); - case 106: /* resolvetype ::= raisetype */ yytestcase(yyruleno==106); -{yygotominor.yy4 = yymsp[0].minor.yy4;} + case 82: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 98: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==98); + case 100: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==100); + case 103: /* resolvetype ::= raisetype */ yytestcase(yyruleno==103); +{yygotominor.yy328 = yymsp[0].minor.yy328;} break; - case 89: /* conslist_opt ::= */ + case 86: /* conslist_opt ::= */ {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;} break; - case 90: /* conslist_opt ::= COMMA conslist */ + case 87: /* conslist_opt ::= COMMA conslist */ {yygotominor.yy0 = yymsp[-1].minor.yy0;} break; - case 93: /* tconscomma ::= COMMA */ + case 90: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; - case 96: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy4,yymsp[-2].minor.yy4,0);} + case 93: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */ +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy328,yymsp[-2].minor.yy328,0);} break; - case 97: /* tcons ::= UNIQUE LP idxlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy4,0,0,0,0);} + case 94: /* tcons ::= UNIQUE LP idxlist RP onconf */ +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy328,0,0,0,0);} break; - case 98: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy118.pExpr);} + case 95: /* tcons ::= CHECK LP expr RP onconf */ +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy346.pExpr);} break; - case 99: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ + case 96: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy4); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy4); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy328); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy328); } break; - case 102: /* onconf ::= */ -{yygotominor.yy4 = OE_Default;} + case 99: /* onconf ::= */ +{yygotominor.yy328 = OE_Default;} break; - case 104: /* orconf ::= */ -{yygotominor.yy210 = OE_Default;} + case 101: /* orconf ::= */ +{yygotominor.yy186 = OE_Default;} break; - case 105: /* orconf ::= OR resolvetype */ -{yygotominor.yy210 = (u8)yymsp[0].minor.yy4;} + case 102: /* orconf ::= OR resolvetype */ +{yygotominor.yy186 = (u8)yymsp[0].minor.yy328;} break; - case 107: /* resolvetype ::= IGNORE */ -{yygotominor.yy4 = OE_Ignore;} + case 104: /* resolvetype ::= IGNORE */ +{yygotominor.yy328 = OE_Ignore;} break; - case 108: /* resolvetype ::= REPLACE */ -{yygotominor.yy4 = OE_Replace;} + case 105: /* resolvetype ::= REPLACE */ +{yygotominor.yy328 = OE_Replace;} break; - case 109: /* cmd ::= DROP TABLE ifexists fullname */ + case 106: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0, yymsp[-1].minor.yy4); + sqlite3DropTable(pParse, yymsp[0].minor.yy65, 0, yymsp[-1].minor.yy328); } break; - case 112: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */ + case 109: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */ { - sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy387, yymsp[-6].minor.yy4, yymsp[-4].minor.yy4); + sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy3, yymsp[-6].minor.yy328, yymsp[-4].minor.yy328); } break; - case 113: /* cmd ::= DROP VIEW ifexists fullname */ + case 110: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1, yymsp[-1].minor.yy4); + sqlite3DropTable(pParse, yymsp[0].minor.yy65, 1, yymsp[-1].minor.yy328); } break; - case 114: /* cmd ::= select */ + case 111: /* cmd ::= select */ { - SelectDest dest = {SRT_Output, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy387, &dest); + SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; + sqlite3Select(pParse, yymsp[0].minor.yy3, &dest); sqlite3ExplainBegin(pParse->pVdbe); - sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy387); + sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy3); sqlite3ExplainFinish(pParse->pVdbe); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3); } break; - case 115: /* select ::= oneselect */ -{yygotominor.yy387 = yymsp[0].minor.yy387;} + case 112: /* select ::= with selectnowith */ +{ + Select *p = yymsp[0].minor.yy3, *pNext, *pLoop; + if( p ){ + int cnt = 0, mxSelect; + p->pWith = yymsp[-1].minor.yy59; + if( p->pPrior ){ + pNext = 0; + for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ + pLoop->pNext = pNext; + pLoop->selFlags |= SF_Compound; + } + mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; + if( mxSelect && cnt>mxSelect ){ + sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); + } + } + }else{ + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59); + } + yygotominor.yy3 = p; +} + break; + case 113: /* selectnowith ::= oneselect */ + case 119: /* oneselect ::= values */ yytestcase(yyruleno==119); +{yygotominor.yy3 = yymsp[0].minor.yy3;} break; - case 116: /* select ::= select multiselect_op oneselect */ + case 114: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - if( yymsp[0].minor.yy387 ){ - yymsp[0].minor.yy387->op = (u8)yymsp[-1].minor.yy4; - yymsp[0].minor.yy387->pPrior = yymsp[-2].minor.yy387; - if( yymsp[-1].minor.yy4!=TK_ALL ) pParse->hasCompound = 1; + Select *pRhs = yymsp[0].minor.yy3; + if( pRhs && pRhs->pPrior ){ + SrcList *pFrom; + Token x; + x.n = 0; + pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); + pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); + } + if( pRhs ){ + pRhs->op = (u8)yymsp[-1].minor.yy328; + pRhs->pPrior = yymsp[-2].minor.yy3; + if( yymsp[-1].minor.yy328!=TK_ALL ) pParse->hasCompound = 1; }else{ - sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy3); } - yygotominor.yy387 = yymsp[0].minor.yy387; + yygotominor.yy3 = pRhs; } break; - case 118: /* multiselect_op ::= UNION ALL */ -{yygotominor.yy4 = TK_ALL;} + case 116: /* multiselect_op ::= UNION ALL */ +{yygotominor.yy328 = TK_ALL;} break; - case 120: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yygotominor.yy387 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy259,yymsp[-4].minor.yy314,yymsp[-3].minor.yy322,yymsp[-2].minor.yy314,yymsp[-1].minor.yy322,yymsp[-7].minor.yy177,yymsp[0].minor.yy292.pLimit,yymsp[0].minor.yy292.pOffset); + yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy65,yymsp[-4].minor.yy132,yymsp[-3].minor.yy14,yymsp[-2].minor.yy132,yymsp[-1].minor.yy14,yymsp[-7].minor.yy381,yymsp[0].minor.yy476.pLimit,yymsp[0].minor.yy476.pOffset); } break; - case 121: /* distinct ::= DISTINCT */ -{yygotominor.yy177 = SF_Distinct;} + case 120: /* values ::= VALUES LP nexprlist RP */ +{ + yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0); +} break; - case 122: /* distinct ::= ALL */ - case 123: /* distinct ::= */ yytestcase(yyruleno==123); -{yygotominor.yy177 = 0;} + case 121: /* values ::= values COMMA LP exprlist RP */ +{ + Select *pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0); + if( pRight ){ + pRight->op = TK_ALL; + pRight->pPrior = yymsp[-4].minor.yy3; + yygotominor.yy3 = pRight; + }else{ + yygotominor.yy3 = yymsp[-4].minor.yy3; + } +} break; - case 124: /* sclp ::= selcollist COMMA */ - case 248: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==248); -{yygotominor.yy322 = yymsp[-1].minor.yy322;} + case 122: /* distinct ::= DISTINCT */ +{yygotominor.yy381 = SF_Distinct;} break; - case 125: /* sclp ::= */ - case 153: /* orderby_opt ::= */ yytestcase(yyruleno==153); - case 160: /* groupby_opt ::= */ yytestcase(yyruleno==160); - case 241: /* exprlist ::= */ yytestcase(yyruleno==241); - case 247: /* idxlist_opt ::= */ yytestcase(yyruleno==247); -{yygotominor.yy322 = 0;} + case 123: /* distinct ::= ALL */ + case 124: /* distinct ::= */ yytestcase(yyruleno==124); +{yygotominor.yy381 = 0;} break; - case 126: /* selcollist ::= sclp expr as */ + case 125: /* sclp ::= selcollist COMMA */ + case 243: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==243); +{yygotominor.yy14 = yymsp[-1].minor.yy14;} + break; + case 126: /* sclp ::= */ + case 154: /* orderby_opt ::= */ yytestcase(yyruleno==154); + case 161: /* groupby_opt ::= */ yytestcase(yyruleno==161); + case 236: /* exprlist ::= */ yytestcase(yyruleno==236); + case 242: /* idxlist_opt ::= */ yytestcase(yyruleno==242); +{yygotominor.yy14 = 0;} + break; + case 127: /* selcollist ::= sclp expr as */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, yymsp[-1].minor.yy118.pExpr); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yygotominor.yy322,&yymsp[-1].minor.yy118); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, yymsp[-1].minor.yy346.pExpr); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yygotominor.yy14,&yymsp[-1].minor.yy346); } break; - case 127: /* selcollist ::= sclp STAR */ + case 128: /* selcollist ::= sclp STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy322, p); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy14, p); } break; - case 128: /* selcollist ::= sclp nm DOT STAR */ + case 129: /* selcollist ::= sclp nm DOT STAR */ { Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, pDot); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, pDot); } break; - case 131: /* as ::= */ + case 132: /* as ::= */ {yygotominor.yy0.n = 0;} break; - case 132: /* from ::= */ -{yygotominor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy259));} + case 133: /* from ::= */ +{yygotominor.yy65 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy65));} break; - case 133: /* from ::= FROM seltablist */ + case 134: /* from ::= FROM seltablist */ { - yygotominor.yy259 = yymsp[0].minor.yy259; - sqlite3SrcListShiftJoinType(yygotominor.yy259); + yygotominor.yy65 = yymsp[0].minor.yy65; + sqlite3SrcListShiftJoinType(yygotominor.yy65); } break; - case 134: /* stl_prefix ::= seltablist joinop */ + case 135: /* stl_prefix ::= seltablist joinop */ { - yygotominor.yy259 = yymsp[-1].minor.yy259; - if( ALWAYS(yygotominor.yy259 && yygotominor.yy259->nSrc>0) ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = (u8)yymsp[0].minor.yy4; + yygotominor.yy65 = yymsp[-1].minor.yy65; + if( ALWAYS(yygotominor.yy65 && yygotominor.yy65->nSrc>0) ) yygotominor.yy65->a[yygotominor.yy65->nSrc-1].jointype = (u8)yymsp[0].minor.yy328; } break; - case 135: /* stl_prefix ::= */ -{yygotominor.yy259 = 0;} + case 136: /* stl_prefix ::= */ +{yygotominor.yy65 = 0;} break; - case 136: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + case 137: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); - sqlite3SrcListIndexedBy(pParse, yygotominor.yy259, &yymsp[-2].minor.yy0); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); + sqlite3SrcListIndexedBy(pParse, yygotominor.yy65, &yymsp[-2].minor.yy0); } break; - case 137: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + case 138: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy3,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); } break; - case 138: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + case 139: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { - if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){ - yygotominor.yy259 = yymsp[-4].minor.yy259; - }else if( yymsp[-4].minor.yy259->nSrc==1 ){ - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); - if( yygotominor.yy259 ){ - struct SrcList_item *pNew = &yygotominor.yy259->a[yygotominor.yy259->nSrc-1]; - struct SrcList_item *pOld = yymsp[-4].minor.yy259->a; + if( yymsp[-6].minor.yy65==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy132==0 && yymsp[0].minor.yy408==0 ){ + yygotominor.yy65 = yymsp[-4].minor.yy65; + }else if( yymsp[-4].minor.yy65->nSrc==1 ){ + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); + if( yygotominor.yy65 ){ + struct SrcList_item *pNew = &yygotominor.yy65->a[yygotominor.yy65->nSrc-1]; + struct SrcList_item *pOld = yymsp[-4].minor.yy65->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy259); + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy65); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy259); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy259,0,0,0,0,SF_NestedFrom,0,0); - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy65); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy65,0,0,0,0,SF_NestedFrom,0,0); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); } } break; - case 139: /* dbnm ::= */ - case 148: /* indexed_opt ::= */ yytestcase(yyruleno==148); + case 140: /* dbnm ::= */ + case 149: /* indexed_opt ::= */ yytestcase(yyruleno==149); {yygotominor.yy0.z=0; yygotominor.yy0.n=0;} break; - case 141: /* fullname ::= nm dbnm */ -{yygotominor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} + case 142: /* fullname ::= nm dbnm */ +{yygotominor.yy65 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; - case 142: /* joinop ::= COMMA|JOIN */ -{ yygotominor.yy4 = JT_INNER; } + case 143: /* joinop ::= COMMA|JOIN */ +{ yygotominor.yy328 = JT_INNER; } break; - case 143: /* joinop ::= JOIN_KW JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } + case 144: /* joinop ::= JOIN_KW JOIN */ +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } break; - case 144: /* joinop ::= JOIN_KW nm JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } + case 145: /* joinop ::= JOIN_KW nm JOIN */ +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } break; - case 145: /* joinop ::= JOIN_KW nm nm JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } + case 146: /* joinop ::= JOIN_KW nm nm JOIN */ +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } break; - case 146: /* on_opt ::= ON expr */ - case 163: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==163); - case 170: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==170); - case 236: /* case_else ::= ELSE expr */ yytestcase(yyruleno==236); - case 238: /* case_operand ::= expr */ yytestcase(yyruleno==238); -{yygotominor.yy314 = yymsp[0].minor.yy118.pExpr;} + case 147: /* on_opt ::= ON expr */ + case 164: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==164); + case 171: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==171); + case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); + case 233: /* case_operand ::= expr */ yytestcase(yyruleno==233); +{yygotominor.yy132 = yymsp[0].minor.yy346.pExpr;} break; - case 147: /* on_opt ::= */ - case 162: /* having_opt ::= */ yytestcase(yyruleno==162); - case 169: /* where_opt ::= */ yytestcase(yyruleno==169); - case 237: /* case_else ::= */ yytestcase(yyruleno==237); - case 239: /* case_operand ::= */ yytestcase(yyruleno==239); -{yygotominor.yy314 = 0;} + case 148: /* on_opt ::= */ + case 163: /* having_opt ::= */ yytestcase(yyruleno==163); + case 170: /* where_opt ::= */ yytestcase(yyruleno==170); + case 232: /* case_else ::= */ yytestcase(yyruleno==232); + case 234: /* case_operand ::= */ yytestcase(yyruleno==234); +{yygotominor.yy132 = 0;} break; - case 150: /* indexed_opt ::= NOT INDEXED */ + case 151: /* indexed_opt ::= NOT INDEXED */ {yygotominor.yy0.z=0; yygotominor.yy0.n=1;} break; - case 151: /* using_opt ::= USING LP idlist RP */ - case 182: /* inscollist_opt ::= LP idlist RP */ yytestcase(yyruleno==182); -{yygotominor.yy384 = yymsp[-1].minor.yy384;} + case 152: /* using_opt ::= USING LP idlist RP */ + case 180: /* inscollist_opt ::= LP idlist RP */ yytestcase(yyruleno==180); +{yygotominor.yy408 = yymsp[-1].minor.yy408;} break; - case 152: /* using_opt ::= */ - case 181: /* inscollist_opt ::= */ yytestcase(yyruleno==181); -{yygotominor.yy384 = 0;} + case 153: /* using_opt ::= */ + case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179); +{yygotominor.yy408 = 0;} break; - case 154: /* orderby_opt ::= ORDER BY sortlist */ - case 161: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==161); - case 240: /* exprlist ::= nexprlist */ yytestcase(yyruleno==240); -{yygotominor.yy322 = yymsp[0].minor.yy322;} + case 155: /* orderby_opt ::= ORDER BY sortlist */ + case 162: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==162); + case 235: /* exprlist ::= nexprlist */ yytestcase(yyruleno==235); +{yygotominor.yy14 = yymsp[0].minor.yy14;} break; - case 155: /* sortlist ::= sortlist COMMA expr sortorder */ + case 156: /* sortlist ::= sortlist COMMA expr sortorder */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy118.pExpr); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14,yymsp[-1].minor.yy346.pExpr); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 156: /* sortlist ::= expr sortorder */ + case 157: /* sortlist ::= expr sortorder */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy118.pExpr); - if( yygotominor.yy322 && ALWAYS(yygotominor.yy322->a) ) yygotominor.yy322->a[0].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy346.pExpr); + if( yygotominor.yy14 && ALWAYS(yygotominor.yy14->a) ) yygotominor.yy14->a[0].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 157: /* sortorder ::= ASC */ - case 159: /* sortorder ::= */ yytestcase(yyruleno==159); -{yygotominor.yy4 = SQLITE_SO_ASC;} + case 158: /* sortorder ::= ASC */ + case 160: /* sortorder ::= */ yytestcase(yyruleno==160); +{yygotominor.yy328 = SQLITE_SO_ASC;} break; - case 158: /* sortorder ::= DESC */ -{yygotominor.yy4 = SQLITE_SO_DESC;} + case 159: /* sortorder ::= DESC */ +{yygotominor.yy328 = SQLITE_SO_DESC;} break; - case 164: /* limit_opt ::= */ -{yygotominor.yy292.pLimit = 0; yygotominor.yy292.pOffset = 0;} + case 165: /* limit_opt ::= */ +{yygotominor.yy476.pLimit = 0; yygotominor.yy476.pOffset = 0;} break; - case 165: /* limit_opt ::= LIMIT expr */ -{yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr; yygotominor.yy292.pOffset = 0;} + case 166: /* limit_opt ::= LIMIT expr */ +{yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr; yygotominor.yy476.pOffset = 0;} break; - case 166: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yygotominor.yy292.pLimit = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pOffset = yymsp[0].minor.yy118.pExpr;} + case 167: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yygotominor.yy476.pLimit = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pOffset = yymsp[0].minor.yy346.pExpr;} break; - case 167: /* limit_opt ::= LIMIT expr COMMA expr */ -{yygotominor.yy292.pOffset = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr;} + case 168: /* limit_opt ::= LIMIT expr COMMA expr */ +{yygotominor.yy476.pOffset = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr;} break; - case 168: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */ + case 169: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314); + sqlite3WithPush(pParse, yymsp[-5].minor.yy59, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy65, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy65,yymsp[0].minor.yy132); } break; - case 171: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */ + case 172: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy210); + sqlite3WithPush(pParse, yymsp[-7].minor.yy59, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy65, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy14,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy65,yymsp[-1].minor.yy14,yymsp[0].minor.yy132,yymsp[-5].minor.yy186); } break; - case 172: /* setlist ::= setlist COMMA nm EQ expr */ + case 173: /* setlist ::= setlist COMMA nm EQ expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy118.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy346.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); } break; - case 173: /* setlist ::= nm EQ expr */ + case 174: /* setlist ::= nm EQ expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy118.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy346.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); } break; - case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy259, yymsp[0].minor.yy260.pList, yymsp[0].minor.yy260.pSelect, yymsp[-1].minor.yy384, yymsp[-4].minor.yy210);} - break; - case 175: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy210);} - break; - case 176: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ -{sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy210);} - break; - case 177: /* insert_cmd ::= INSERT orconf */ -{yygotominor.yy210 = yymsp[0].minor.yy210;} - break; - case 178: /* insert_cmd ::= REPLACE */ -{yygotominor.yy210 = OE_Replace;} - break; - case 179: /* valuelist ::= VALUES LP nexprlist RP */ + case 175: /* cmd ::= with insert_cmd INTO fullname inscollist_opt select */ { - yygotominor.yy260.pList = yymsp[-1].minor.yy322; - yygotominor.yy260.pSelect = 0; + sqlite3WithPush(pParse, yymsp[-5].minor.yy59, 1); + sqlite3Insert(pParse, yymsp[-2].minor.yy65, yymsp[0].minor.yy3, yymsp[-1].minor.yy408, yymsp[-4].minor.yy186); } break; - case 180: /* valuelist ::= valuelist COMMA LP exprlist RP */ + case 176: /* cmd ::= with insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ { - Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy322, 0, 0, 0, 0, 0, 0, 0, 0); - if( yymsp[-4].minor.yy260.pList ){ - yymsp[-4].minor.yy260.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy260.pList, 0, 0, 0, 0, 0, 0, 0, 0); - yymsp[-4].minor.yy260.pList = 0; - } - yygotominor.yy260.pList = 0; - if( yymsp[-4].minor.yy260.pSelect==0 || pRight==0 ){ - sqlite3SelectDelete(pParse->db, pRight); - sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy260.pSelect); - yygotominor.yy260.pSelect = 0; - }else{ - pRight->op = TK_ALL; - pRight->pPrior = yymsp[-4].minor.yy260.pSelect; - pRight->selFlags |= SF_Values; - pRight->pPrior->selFlags |= SF_Values; - yygotominor.yy260.pSelect = pRight; - } + sqlite3WithPush(pParse, yymsp[-6].minor.yy59, 1); + sqlite3Insert(pParse, yymsp[-3].minor.yy65, 0, yymsp[-2].minor.yy408, yymsp[-5].minor.yy186); } break; - case 183: /* idlist ::= idlist COMMA nm */ -{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);} + case 177: /* insert_cmd ::= INSERT orconf */ +{yygotominor.yy186 = yymsp[0].minor.yy186;} + break; + case 178: /* insert_cmd ::= REPLACE */ +{yygotominor.yy186 = OE_Replace;} + break; + case 181: /* idlist ::= idlist COMMA nm */ +{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy408,&yymsp[0].minor.yy0);} break; - case 184: /* idlist ::= nm */ -{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} + case 182: /* idlist ::= nm */ +{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} break; - case 185: /* expr ::= term */ -{yygotominor.yy118 = yymsp[0].minor.yy118;} + case 183: /* expr ::= term */ +{yygotominor.yy346 = yymsp[0].minor.yy346;} break; - case 186: /* expr ::= LP expr RP */ -{yygotominor.yy118.pExpr = yymsp[-1].minor.yy118.pExpr; spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} + case 184: /* expr ::= LP expr RP */ +{yygotominor.yy346.pExpr = yymsp[-1].minor.yy346.pExpr; spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} break; - case 187: /* term ::= NULL */ - case 192: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==192); - case 193: /* term ::= STRING */ yytestcase(yyruleno==193); -{spanExpr(&yygotominor.yy118, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} + case 185: /* term ::= NULL */ + case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190); + case 191: /* term ::= STRING */ yytestcase(yyruleno==191); +{spanExpr(&yygotominor.yy346, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} break; - case 188: /* expr ::= id */ - case 189: /* expr ::= JOIN_KW */ yytestcase(yyruleno==189); -{spanExpr(&yygotominor.yy118, pParse, TK_ID, &yymsp[0].minor.yy0);} + case 186: /* expr ::= ID|INDEXED */ + case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187); +{spanExpr(&yygotominor.yy346, pParse, TK_ID, &yymsp[0].minor.yy0);} break; - case 190: /* expr ::= nm DOT nm */ + case 188: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); - spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } break; - case 191: /* expr ::= nm DOT nm DOT nm */ + case 189: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); - spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); } break; - case 194: /* expr ::= REGISTER */ + case 192: /* expr ::= VARIABLE */ { - /* When doing a nested parse, one can include terms in an expression - ** that look like this: #1 #2 ... These terms refer to registers - ** in the virtual machine. #N is the N-th register. */ - if( pParse->nested==0 ){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = 0; + if( yymsp[0].minor.yy0.n>=2 && yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1]) ){ + /* When doing a nested parse, one can include terms in an expression + ** that look like this: #1 #2 ... These terms refer to registers + ** in the virtual machine. #N is the N-th register. */ + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = 0; + }else{ + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); + if( yygotominor.yy346.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy346.pExpr->iTable); + } }else{ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); - if( yygotominor.yy118.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy118.pExpr->iTable); + spanExpr(&yygotominor.yy346, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yygotominor.yy346.pExpr); } - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; - case 195: /* expr ::= VARIABLE */ + case 193: /* expr ::= expr COLLATE ID|STRING */ { - spanExpr(&yygotominor.yy118, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yygotominor.yy118.pExpr); - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0); + yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 196: /* expr ::= expr COLLATE ids */ + case 194: /* expr ::= CAST LP expr AS typetoken RP */ { - yygotominor.yy118.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy118.pExpr, &yymsp[0].minor.yy0); - yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy346.pExpr, 0, &yymsp[-1].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } break; - case 197: /* expr ::= CAST LP expr AS typetoken RP */ + case 195: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy118.pExpr, 0, &yymsp[-1].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); -} - break; - case 198: /* expr ::= ID LP distinct exprlist RP */ -{ - if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + if( yymsp[-1].minor.yy14 && yymsp[-1].minor.yy14->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy177 && yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->flags |= EP_Distinct; + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy381 && yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->flags |= EP_Distinct; } } break; - case 199: /* expr ::= ID LP STAR RP */ + case 196: /* expr ::= ID|INDEXED LP STAR RP */ { - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } break; - case 200: /* term ::= CTIME_KW */ + case 197: /* term ::= CTIME_KW */ { - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; - case 201: /* expr ::= expr AND expr */ - case 202: /* expr ::= expr OR expr */ yytestcase(yyruleno==202); - case 203: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==203); - case 204: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==204); - case 205: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==205); - case 206: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==206); - case 207: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==207); - case 208: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==208); -{spanBinaryExpr(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);} + case 198: /* expr ::= expr AND expr */ + case 199: /* expr ::= expr OR expr */ yytestcase(yyruleno==199); + case 200: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==200); + case 201: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==201); + case 202: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==202); + case 203: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==203); + case 204: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==204); + case 205: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==205); +{spanBinaryExpr(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346);} break; - case 209: /* likeop ::= LIKE_KW */ - case 211: /* likeop ::= MATCH */ yytestcase(yyruleno==211); -{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.bNot = 0;} + case 206: /* likeop ::= LIKE_KW|MATCH */ +{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.bNot = 0;} break; - case 210: /* likeop ::= NOT LIKE_KW */ - case 212: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==212); -{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.bNot = 1;} + case 207: /* likeop ::= NOT LIKE_KW|MATCH */ +{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.bNot = 1;} break; - case 213: /* expr ::= expr likeop expr */ + case 208: /* expr ::= expr likeop expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy342.eOperator); - if( yymsp[-1].minor.yy342.bNot ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; - if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy96.eOperator); + if( yymsp[-1].minor.yy96.bNot ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; + if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc; } break; - case 214: /* expr ::= expr likeop expr ESCAPE expr */ + case 209: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy342.eOperator); - if( yymsp[-3].minor.yy342.bNot ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; - if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy96.eOperator); + if( yymsp[-3].minor.yy96.bNot ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; + if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc; } break; - case 215: /* expr ::= expr ISNULL|NOTNULL */ -{spanUnaryPostfix(&yygotominor.yy118,pParse,yymsp[0].major,&yymsp[-1].minor.yy118,&yymsp[0].minor.yy0);} + case 210: /* expr ::= expr ISNULL|NOTNULL */ +{spanUnaryPostfix(&yygotominor.yy346,pParse,yymsp[0].major,&yymsp[-1].minor.yy346,&yymsp[0].minor.yy0);} break; - case 216: /* expr ::= expr NOT NULL */ -{spanUnaryPostfix(&yygotominor.yy118,pParse,TK_NOTNULL,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy0);} + case 211: /* expr ::= expr NOT NULL */ +{spanUnaryPostfix(&yygotominor.yy346,pParse,TK_NOTNULL,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy0);} break; - case 217: /* expr ::= expr IS expr */ + case 212: /* expr ::= expr IS expr */ { - spanBinaryExpr(&yygotominor.yy118,pParse,TK_IS,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_ISNULL); + spanBinaryExpr(&yygotominor.yy346,pParse,TK_IS,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy346.pExpr, yygotominor.yy346.pExpr, TK_ISNULL); } break; - case 218: /* expr ::= expr IS NOT expr */ + case 213: /* expr ::= expr IS NOT expr */ { - spanBinaryExpr(&yygotominor.yy118,pParse,TK_ISNOT,&yymsp[-3].minor.yy118,&yymsp[0].minor.yy118); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_NOTNULL); + spanBinaryExpr(&yygotominor.yy346,pParse,TK_ISNOT,&yymsp[-3].minor.yy346,&yymsp[0].minor.yy346); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy346.pExpr, yygotominor.yy346.pExpr, TK_NOTNULL); } break; - case 219: /* expr ::= NOT expr */ - case 220: /* expr ::= BITNOT expr */ yytestcase(yyruleno==220); -{spanUnaryPrefix(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 214: /* expr ::= NOT expr */ + case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); +{spanUnaryPrefix(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; - case 221: /* expr ::= MINUS expr */ -{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UMINUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 216: /* expr ::= MINUS expr */ +{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UMINUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; - case 222: /* expr ::= PLUS expr */ -{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UPLUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 217: /* expr ::= PLUS expr */ +{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UPLUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; - case 225: /* expr ::= expr between_op expr AND expr */ + case 220: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; } break; - case 228: /* expr ::= expr in_op LP exprlist RP */ + case 223: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy322==0 ){ + if( yymsp[-1].minor.yy14==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -117189,225 +118218,225 @@ static void yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy4]); - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy328]); + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy346.pExpr); }else{ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy322; - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14; + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); } - if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); } - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 229: /* expr ::= LP select RP */ + case 224: /* expr ::= LP select RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } - yygotominor.yy118.zStart = yymsp[-2].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-2].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 230: /* expr ::= expr in_op LP select RP */ + case 225: /* expr ::= expr in_op LP select RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } - if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 231: /* expr ::= expr in_op nm dbnm */ + case 226: /* expr ::= expr in_op nm dbnm */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - if( yymsp[-2].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-3].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; + if( yymsp[-2].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-3].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; } break; - case 232: /* expr ::= EXISTS LP select RP */ + case 227: /* expr ::= EXISTS LP select RP */ { - Expr *p = yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ - p->x.pSelect = yymsp[-1].minor.yy387; + p->x.pSelect = yymsp[-1].minor.yy3; ExprSetProperty(p, EP_xIsSelect); sqlite3ExprSetHeight(pParse, p); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } - yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 233: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy314 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy314) : yymsp[-2].minor.yy322; - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy132, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy132 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy132) : yymsp[-2].minor.yy14; + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy314); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy132); } - yygotominor.yy118.zStart = yymsp[-4].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-4].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 234: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr); } break; - case 235: /* case_exprlist ::= WHEN expr THEN expr */ + case 230: /* case_exprlist ::= WHEN expr THEN expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr); } break; - case 242: /* nexprlist ::= nexprlist COMMA expr */ -{yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy118.pExpr);} + case 237: /* nexprlist ::= nexprlist COMMA expr */ +{yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy346.pExpr);} break; - case 243: /* nexprlist ::= expr */ -{yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy118.pExpr);} + case 238: /* nexprlist ::= expr */ +{yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy346.pExpr);} break; - case 244: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */ + case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy4, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy314, SQLITE_SO_ASC, yymsp[-8].minor.yy4); + sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy328, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy132, SQLITE_SO_ASC, yymsp[-8].minor.yy328); } break; - case 245: /* uniqueflag ::= UNIQUE */ - case 298: /* raisetype ::= ABORT */ yytestcase(yyruleno==298); -{yygotominor.yy4 = OE_Abort;} + case 240: /* uniqueflag ::= UNIQUE */ + case 291: /* raisetype ::= ABORT */ yytestcase(yyruleno==291); +{yygotominor.yy328 = OE_Abort;} break; - case 246: /* uniqueflag ::= */ -{yygotominor.yy4 = OE_None;} + case 241: /* uniqueflag ::= */ +{yygotominor.yy328 = OE_None;} break; - case 249: /* idxlist ::= idxlist COMMA nm collate sortorder */ + case 244: /* idxlist ::= idxlist COMMA nm collate sortorder */ { Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, p); - sqlite3ExprListSetName(pParse,yygotominor.yy322,&yymsp[-2].minor.yy0,1); - sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index"); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, p); + sqlite3ExprListSetName(pParse,yygotominor.yy14,&yymsp[-2].minor.yy0,1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 250: /* idxlist ::= nm collate sortorder */ + case 245: /* idxlist ::= nm collate sortorder */ { Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, p); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); - sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index"); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, p); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 251: /* collate ::= */ + case 246: /* collate ::= */ {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;} break; - case 253: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);} + case 248: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy65, yymsp[-1].minor.yy328);} break; - case 254: /* cmd ::= VACUUM */ - case 255: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==255); + case 249: /* cmd ::= VACUUM */ + case 250: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==250); {sqlite3Vacuum(pParse);} break; - case 256: /* cmd ::= PRAGMA nm dbnm */ + case 251: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 257: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 252: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 258: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 259: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 254: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 260: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 255: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 270: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 264: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy473, &all); } break; - case 271: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 265: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy328, yymsp[-4].minor.yy378.a, yymsp[-4].minor.yy378.b, yymsp[-2].minor.yy65, yymsp[0].minor.yy132, yymsp[-10].minor.yy328, yymsp[-8].minor.yy328); yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); } break; - case 272: /* trigger_time ::= BEFORE */ - case 275: /* trigger_time ::= */ yytestcase(yyruleno==275); -{ yygotominor.yy4 = TK_BEFORE; } + case 266: /* trigger_time ::= BEFORE */ + case 269: /* trigger_time ::= */ yytestcase(yyruleno==269); +{ yygotominor.yy328 = TK_BEFORE; } break; - case 273: /* trigger_time ::= AFTER */ -{ yygotominor.yy4 = TK_AFTER; } + case 267: /* trigger_time ::= AFTER */ +{ yygotominor.yy328 = TK_AFTER; } break; - case 274: /* trigger_time ::= INSTEAD OF */ -{ yygotominor.yy4 = TK_INSTEAD;} + case 268: /* trigger_time ::= INSTEAD OF */ +{ yygotominor.yy328 = TK_INSTEAD;} break; - case 276: /* trigger_event ::= DELETE|INSERT */ - case 277: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==277); -{yygotominor.yy90.a = yymsp[0].major; yygotominor.yy90.b = 0;} + case 270: /* trigger_event ::= DELETE|INSERT */ + case 271: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==271); +{yygotominor.yy378.a = yymsp[0].major; yygotominor.yy378.b = 0;} break; - case 278: /* trigger_event ::= UPDATE OF idlist */ -{yygotominor.yy90.a = TK_UPDATE; yygotominor.yy90.b = yymsp[0].minor.yy384;} + case 272: /* trigger_event ::= UPDATE OF idlist */ +{yygotominor.yy378.a = TK_UPDATE; yygotominor.yy378.b = yymsp[0].minor.yy408;} break; - case 281: /* when_clause ::= */ - case 303: /* key_opt ::= */ yytestcase(yyruleno==303); -{ yygotominor.yy314 = 0; } + case 275: /* when_clause ::= */ + case 296: /* key_opt ::= */ yytestcase(yyruleno==296); +{ yygotominor.yy132 = 0; } break; - case 282: /* when_clause ::= WHEN expr */ - case 304: /* key_opt ::= KEY expr */ yytestcase(yyruleno==304); -{ yygotominor.yy314 = yymsp[0].minor.yy118.pExpr; } + case 276: /* when_clause ::= WHEN expr */ + case 297: /* key_opt ::= KEY expr */ yytestcase(yyruleno==297); +{ yygotominor.yy132 = yymsp[0].minor.yy346.pExpr; } break; - case 283: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 277: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy203!=0 ); - yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203; - yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203; - yygotominor.yy203 = yymsp[-2].minor.yy203; + assert( yymsp[-2].minor.yy473!=0 ); + yymsp[-2].minor.yy473->pLast->pNext = yymsp[-1].minor.yy473; + yymsp[-2].minor.yy473->pLast = yymsp[-1].minor.yy473; + yygotominor.yy473 = yymsp[-2].minor.yy473; } break; - case 284: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 278: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy203!=0 ); - yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203; - yygotominor.yy203 = yymsp[-1].minor.yy203; + assert( yymsp[-1].minor.yy473!=0 ); + yymsp[-1].minor.yy473->pLast = yymsp[-1].minor.yy473; + yygotominor.yy473 = yymsp[-1].minor.yy473; } break; - case 286: /* trnm ::= nm DOT nm */ + case 280: /* trnm ::= nm DOT nm */ { yygotominor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -117415,123 +118444,137 @@ static void yy_reduce( "statements within triggers"); } break; - case 288: /* tridxby ::= INDEXED BY nm */ + case 282: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 289: /* tridxby ::= NOT INDEXED */ + case 283: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 290: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ -{ yygotominor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy322, yymsp[0].minor.yy314, yymsp[-5].minor.yy210); } + case 284: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ +{ yygotominor.yy473 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy14, yymsp[0].minor.yy132, yymsp[-5].minor.yy186); } break; - case 291: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */ -{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, yymsp[0].minor.yy260.pList, yymsp[0].minor.yy260.pSelect, yymsp[-4].minor.yy210);} + case 285: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ +{yygotominor.yy473 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy408, yymsp[0].minor.yy3, yymsp[-4].minor.yy186);} break; - case 292: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ -{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, 0, yymsp[0].minor.yy387, yymsp[-4].minor.yy210);} + case 286: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ +{yygotominor.yy473 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy132);} break; - case 293: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ -{yygotominor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy314);} + case 287: /* trigger_cmd ::= select */ +{yygotominor.yy473 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy3); } break; - case 294: /* trigger_cmd ::= select */ -{yygotominor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy387); } - break; - case 295: /* expr ::= RAISE LP IGNORE RP */ + case 288: /* expr ::= RAISE LP IGNORE RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->affinity = OE_Ignore; + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->affinity = OE_Ignore; } - yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 296: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 289: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yygotominor.yy118.pExpr ) { - yygotominor.yy118.pExpr->affinity = (char)yymsp[-3].minor.yy4; + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); + if( yygotominor.yy346.pExpr ) { + yygotominor.yy346.pExpr->affinity = (char)yymsp[-3].minor.yy328; } - yygotominor.yy118.zStart = yymsp[-5].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-5].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 297: /* raisetype ::= ROLLBACK */ -{yygotominor.yy4 = OE_Rollback;} + case 290: /* raisetype ::= ROLLBACK */ +{yygotominor.yy328 = OE_Rollback;} break; - case 299: /* raisetype ::= FAIL */ -{yygotominor.yy4 = OE_Fail;} + case 292: /* raisetype ::= FAIL */ +{yygotominor.yy328 = OE_Fail;} break; - case 300: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 293: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy65,yymsp[-1].minor.yy328); } break; - case 301: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 294: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy118.pExpr, yymsp[-1].minor.yy118.pExpr, yymsp[0].minor.yy314); + sqlite3Attach(pParse, yymsp[-3].minor.yy346.pExpr, yymsp[-1].minor.yy346.pExpr, yymsp[0].minor.yy132); } break; - case 302: /* cmd ::= DETACH database_kw_opt expr */ + case 295: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy118.pExpr); + sqlite3Detach(pParse, yymsp[0].minor.yy346.pExpr); } break; - case 307: /* cmd ::= REINDEX */ + case 300: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 308: /* cmd ::= REINDEX nm dbnm */ + case 301: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 309: /* cmd ::= ANALYZE */ + case 302: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 310: /* cmd ::= ANALYZE nm dbnm */ + case 303: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 311: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 304: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy65,&yymsp[0].minor.yy0); } break; - case 312: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ + case 305: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ { sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); } break; - case 313: /* add_column_fullname ::= fullname */ + case 306: /* add_column_fullname ::= fullname */ { pParse->db->lookaside.bEnabled = 0; - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy65); } break; - case 316: /* cmd ::= create_vtab */ + case 309: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 317: /* cmd ::= create_vtab LP vtabarglist RP */ + case 310: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 318: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 311: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy4); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy328); } break; - case 321: /* vtabarg ::= */ + case 314: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 323: /* vtabargtoken ::= ANY */ - case 324: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==324); - case 325: /* lp ::= LP */ yytestcase(yyruleno==325); + case 316: /* vtabargtoken ::= ANY */ + case 317: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==317); + case 318: /* lp ::= LP */ yytestcase(yyruleno==318); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; + case 322: /* with ::= */ +{yygotominor.yy59 = 0;} + break; + case 323: /* with ::= WITH wqlist */ + case 324: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==324); +{ yygotominor.yy59 = yymsp[0].minor.yy59; } + break; + case 325: /* wqlist ::= nm idxlist_opt AS LP select RP */ +{ + yygotominor.yy59 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy3); +} + break; + case 326: /* wqlist ::= wqlist COMMA nm idxlist_opt AS LP select RP */ +{ + yygotominor.yy59 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy59, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy3); +} + break; default: /* (0) input ::= cmdlist */ yytestcase(yyruleno==0); /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1); @@ -117546,28 +118589,28 @@ static void yy_reduce( /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25); /* (36) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==36); /* (37) columnlist ::= column */ yytestcase(yyruleno==37); - /* (46) type ::= */ yytestcase(yyruleno==46); - /* (53) signed ::= plus_num */ yytestcase(yyruleno==53); - /* (54) signed ::= minus_num */ yytestcase(yyruleno==54); - /* (55) carglist ::= carglist ccons */ yytestcase(yyruleno==55); - /* (56) carglist ::= */ yytestcase(yyruleno==56); - /* (63) ccons ::= NULL onconf */ yytestcase(yyruleno==63); - /* (91) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==91); - /* (92) conslist ::= tcons */ yytestcase(yyruleno==92); - /* (94) tconscomma ::= */ yytestcase(yyruleno==94); - /* (279) foreach_clause ::= */ yytestcase(yyruleno==279); - /* (280) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==280); - /* (287) tridxby ::= */ yytestcase(yyruleno==287); - /* (305) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==305); - /* (306) database_kw_opt ::= */ yytestcase(yyruleno==306); - /* (314) kwcolumn_opt ::= */ yytestcase(yyruleno==314); - /* (315) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==315); - /* (319) vtabarglist ::= vtabarg */ yytestcase(yyruleno==319); - /* (320) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==320); - /* (322) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==322); - /* (326) anylist ::= */ yytestcase(yyruleno==326); - /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); - /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); + /* (43) type ::= */ yytestcase(yyruleno==43); + /* (50) signed ::= plus_num */ yytestcase(yyruleno==50); + /* (51) signed ::= minus_num */ yytestcase(yyruleno==51); + /* (52) carglist ::= carglist ccons */ yytestcase(yyruleno==52); + /* (53) carglist ::= */ yytestcase(yyruleno==53); + /* (60) ccons ::= NULL onconf */ yytestcase(yyruleno==60); + /* (88) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==88); + /* (89) conslist ::= tcons */ yytestcase(yyruleno==89); + /* (91) tconscomma ::= */ yytestcase(yyruleno==91); + /* (273) foreach_clause ::= */ yytestcase(yyruleno==273); + /* (274) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==274); + /* (281) tridxby ::= */ yytestcase(yyruleno==281); + /* (298) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==298); + /* (299) database_kw_opt ::= */ yytestcase(yyruleno==299); + /* (307) kwcolumn_opt ::= */ yytestcase(yyruleno==307); + /* (308) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==308); + /* (312) vtabarglist ::= vtabarg */ yytestcase(yyruleno==312); + /* (313) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==313); + /* (315) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==315); + /* (319) anylist ::= */ yytestcase(yyruleno==319); + /* (320) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==320); + /* (321) anylist ::= anylist ANY */ yytestcase(yyruleno==321); break; }; assert( yyruleno>=0 && yyruleno1 ){ - /* Parameters of the form #NNN (where NNN is a number) are used - ** internally by sqlite3NestedParse. */ - *tokenType = TK_REGISTER; - return i; - } - /* Fall through into the next case if the '#' is not followed by - ** a digit. Try to match #AAAA where AAAA is a parameter name. */ - } #ifndef SQLITE_OMIT_TCL_VARIABLE case '$': #endif case '@': /* For compatibility with MS SQL Server */ + case '#': case ':': { int n = 0; - testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' ); + testcase( z[0]=='$' ); testcase( z[0]=='@' ); + testcase( z[0]==':' ); testcase( z[0]=='#' ); *tokenType = TK_VARIABLE; for(i=1; (c=z[i])!=0; i++){ if( IdChar(c) ){ @@ -118608,6 +119644,7 @@ abort_parse: sqlite3DeleteTable(db, pParse->pNewTable); } + if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith); sqlite3DeleteTrigger(db, pParse->pNewTrigger); for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); sqlite3DbFree(db, pParse->azVar); @@ -119138,13 +120175,6 @@ SQLITE_API int sqlite3_initialize(void){ */ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; -#ifdef SQLITE_ENABLE_SQLLOG - { - extern void sqlite3_init_sqllog(void); - sqlite3_init_sqllog(); - } -#endif - /* Make sure the mutex subsystem is initialized. If unable to ** initialize the mutex subsystem, return early with the error. ** If the system is so sick that we are unable to allocate a mutex, @@ -119591,7 +120621,8 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ db->lookaside.bEnabled = 1; db->lookaside.bMalloced = pBuf==0 ?1:0; }else{ - db->lookaside.pEnd = 0; + db->lookaside.pStart = db; + db->lookaside.pEnd = db; db->lookaside.bEnabled = 0; db->lookaside.bMalloced = 0; } @@ -119989,9 +121020,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ #endif sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ - if( db->pErr ){ - sqlite3ValueFree(db->pErr); - } + sqlite3ValueFree(db->pErr); sqlite3CloseExtensions(db); db->magic = SQLITE_MAGIC_ERROR; @@ -120066,8 +121095,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** Return a static string containing the name corresponding to the error code ** specified in the argument. */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \ - defined(SQLITE_DEBUG_OS_TRACE) +#if defined(SQLITE_TEST) SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ const char *zName = 0; int i, origRc = rc; @@ -120089,6 +121117,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; + case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; @@ -120373,6 +121402,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( ){ FuncDef *p; int nName; + int extraFlags; assert( sqlite3_mutex_held(db->mutex) ); if( zFunctionName==0 || @@ -120383,6 +121413,10 @@ SQLITE_PRIVATE int sqlite3CreateFunc( (255<(nName = sqlite3Strlen30( zFunctionName))) ){ return SQLITE_MISUSE_BKPT; } + + assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); + extraFlags = enc & SQLITE_DETERMINISTIC; + enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); #ifndef SQLITE_OMIT_UTF16 /* If SQLITE_UTF16 is specified as the encoding type, transform this @@ -120396,10 +121430,10 @@ SQLITE_PRIVATE int sqlite3CreateFunc( enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, pUserData, xFunc, xStep, xFinal, pDestructor); if( rc==SQLITE_OK ){ - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, pUserData, xFunc, xStep, xFinal, pDestructor); } if( rc!=SQLITE_OK ){ @@ -120442,7 +121476,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc( pDestructor->nRef++; } p->pDestructor = pDestructor; - p->funcFlags &= SQLITE_FUNC_ENCMASK; + p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; + testcase( p->funcFlags & SQLITE_DETERMINISTIC ); p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; @@ -120872,6 +121907,7 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ if( db->mallocFailed ){ z = sqlite3ErrStr(SQLITE_NOMEM); }else{ + testcase( db->pErr==0 ); z = (char*)sqlite3_value_text(db->pErr); assert( !db->mallocFailed ); if( z==0 ){ @@ -120913,8 +121949,7 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ }else{ z = sqlite3_value_text16(db->pErr); if( z==0 ){ - sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), - SQLITE_UTF8, SQLITE_STATIC); + sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode)); z = sqlite3_value_text16(db->pErr); } /* A malloc() may have failed within the call to sqlite3_value_text16() @@ -121628,8 +122663,6 @@ static int openDatabase( } #endif - sqlite3Error(db, rc, 0); - /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. @@ -121640,6 +122673,8 @@ static int openDatabase( SQLITE_DEFAULT_LOCKING_MODE); #endif + if( rc ) sqlite3Error(db, rc, 0); + /* Enable the lookaside-malloc subsystem */ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, sqlite3GlobalConfig.nLookaside); @@ -122099,7 +123134,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** to the xRandomness method of the default VFS. */ case SQLITE_TESTCTRL_PRNG_RESET: { - sqlite3PrngResetState(); + sqlite3_randomness(0,0); break; } @@ -122308,7 +123343,22 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** that demonstrat invariants on well-formed database files. */ case SQLITE_TESTCTRL_NEVER_CORRUPT: { - sqlite3Config.neverCorrupt = va_arg(ap, int); + sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int); + break; + } + + + /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); + ** + ** Set the VDBE coverage callback function to xCallback with context + ** pointer ptr. + */ + case SQLITE_TESTCTRL_VDBE_COVERAGE: { +#ifdef SQLITE_VDBE_COVERAGE + typedef void (*branch_callback)(void*,int,u8,u8); + sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback); + sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*); +#endif break; } @@ -125083,6 +126133,19 @@ static int fts3CreateMethod( return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr); } +/* +** Set the pIdxInfo->estimatedRows variable to nRow. Unless this +** extension is currently being used by a version of SQLite too old to +** support estimatedRows. In that case this function is a no-op. +*/ +static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ +#if SQLITE_VERSION_NUMBER>=3008002 + if( sqlite3_libversion_number()>=3008002 ){ + pIdxInfo->estimatedRows = nRow; + } +#endif +} + /* ** Implementation of the xBestIndex method for FTS3 tables. There ** are three possible strategies, in order of preference: @@ -125110,7 +126173,20 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ for(i=0; inConstraint; i++){ int bDocid; /* True if this constraint is on docid */ struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; - if( pCons->usable==0 ) continue; + if( pCons->usable==0 ){ + if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ + /* There exists an unusable MATCH constraint. This means that if + ** the planner does elect to use the results of this call as part + ** of the overall query plan the user will see an "unable to use + ** function MATCH in the requested context" error. To discourage + ** this, return a very high cost here. */ + pInfo->idxNum = FTS3_FULLSCAN_SEARCH; + pInfo->estimatedCost = 1e50; + fts3SetEstimatedRows(pInfo, ((sqlite3_int64)1) << 50); + return SQLITE_OK; + } + continue; + } bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1); @@ -131280,13 +132356,13 @@ SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash *pH){ */ static int fts3StrHash(const void *pKey, int nKey){ const char *z = (const char *)pKey; - int h = 0; + unsigned h = 0; if( nKey<=0 ) nKey = (int) strlen(z); while( nKey > 0 ){ h = (h<<3) ^ h ^ *z++; nKey--; } - return h & 0x7fffffff; + return (int)(h & 0x7fffffff); } static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ if( n1!=n2 ) return 1; @@ -131971,12 +133047,14 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ /* Step 2 */ switch( z[1] ){ case 'a': - stem(&z, "lanoita", "ate", m_gt_0) || - stem(&z, "lanoit", "tion", m_gt_0); + if( !stem(&z, "lanoita", "ate", m_gt_0) ){ + stem(&z, "lanoit", "tion", m_gt_0); + } break; case 'c': - stem(&z, "icne", "ence", m_gt_0) || - stem(&z, "icna", "ance", m_gt_0); + if( !stem(&z, "icne", "ence", m_gt_0) ){ + stem(&z, "icna", "ance", m_gt_0); + } break; case 'e': stem(&z, "rezi", "ize", m_gt_0); @@ -131985,43 +133063,54 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ stem(&z, "igol", "log", m_gt_0); break; case 'l': - stem(&z, "ilb", "ble", m_gt_0) || - stem(&z, "illa", "al", m_gt_0) || - stem(&z, "iltne", "ent", m_gt_0) || - stem(&z, "ile", "e", m_gt_0) || - stem(&z, "ilsuo", "ous", m_gt_0); + if( !stem(&z, "ilb", "ble", m_gt_0) + && !stem(&z, "illa", "al", m_gt_0) + && !stem(&z, "iltne", "ent", m_gt_0) + && !stem(&z, "ile", "e", m_gt_0) + ){ + stem(&z, "ilsuo", "ous", m_gt_0); + } break; case 'o': - stem(&z, "noitazi", "ize", m_gt_0) || - stem(&z, "noita", "ate", m_gt_0) || - stem(&z, "rota", "ate", m_gt_0); + if( !stem(&z, "noitazi", "ize", m_gt_0) + && !stem(&z, "noita", "ate", m_gt_0) + ){ + stem(&z, "rota", "ate", m_gt_0); + } break; case 's': - stem(&z, "msila", "al", m_gt_0) || - stem(&z, "ssenevi", "ive", m_gt_0) || - stem(&z, "ssenluf", "ful", m_gt_0) || - stem(&z, "ssensuo", "ous", m_gt_0); + if( !stem(&z, "msila", "al", m_gt_0) + && !stem(&z, "ssenevi", "ive", m_gt_0) + && !stem(&z, "ssenluf", "ful", m_gt_0) + ){ + stem(&z, "ssensuo", "ous", m_gt_0); + } break; case 't': - stem(&z, "itila", "al", m_gt_0) || - stem(&z, "itivi", "ive", m_gt_0) || - stem(&z, "itilib", "ble", m_gt_0); + if( !stem(&z, "itila", "al", m_gt_0) + && !stem(&z, "itivi", "ive", m_gt_0) + ){ + stem(&z, "itilib", "ble", m_gt_0); + } break; } /* Step 3 */ switch( z[0] ){ case 'e': - stem(&z, "etaci", "ic", m_gt_0) || - stem(&z, "evita", "", m_gt_0) || - stem(&z, "ezila", "al", m_gt_0); + if( !stem(&z, "etaci", "ic", m_gt_0) + && !stem(&z, "evita", "", m_gt_0) + ){ + stem(&z, "ezila", "al", m_gt_0); + } break; case 'i': stem(&z, "itici", "ic", m_gt_0); break; case 'l': - stem(&z, "laci", "ic", m_gt_0) || - stem(&z, "luf", "", m_gt_0); + if( !stem(&z, "laci", "ic", m_gt_0) ){ + stem(&z, "luf", "", m_gt_0); + } break; case 's': stem(&z, "ssen", "", m_gt_0); @@ -132062,9 +133151,11 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ z += 3; } }else if( z[2]=='e' ){ - stem(&z, "tneme", "", m_gt_1) || - stem(&z, "tnem", "", m_gt_1) || - stem(&z, "tne", "", m_gt_1); + if( !stem(&z, "tneme", "", m_gt_1) + && !stem(&z, "tnem", "", m_gt_1) + ){ + stem(&z, "tne", "", m_gt_1); + } } } break; @@ -132083,8 +133174,9 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ } break; case 't': - stem(&z, "eta", "", m_gt_1) || - stem(&z, "iti", "", m_gt_1); + if( !stem(&z, "eta", "", m_gt_1) ){ + stem(&z, "iti", "", m_gt_1); + } break; case 'u': if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ diff --git a/src/3rdparty/sqlite/sqlite3.h b/src/3rdparty/sqlite/sqlite3.h index 59b9570b85..1f19ada4cb 100644 --- a/src/3rdparty/sqlite/sqlite3.h +++ b/src/3rdparty/sqlite/sqlite3.h @@ -107,9 +107,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.8.2" -#define SQLITE_VERSION_NUMBER 3008002 -#define SQLITE_SOURCE_ID "2013-12-06 14:53:30 27392118af4c38c5203a04b8013e1afdb1cebd0d" +#define SQLITE_VERSION "3.8.4.1" +#define SQLITE_VERSION_NUMBER 3008004 +#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -491,6 +491,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) @@ -558,7 +559,8 @@ SQLITE_API int sqlite3_exec( ** after reboot following a crash or power loss, the only bytes in a ** file that were written at the application level might have changed ** and that adjacent bytes, even bytes within the same sector are -** guaranteed to be unchanged. +** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN +** flag indicate that a file cannot be deleted when open. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 @@ -789,15 +791,29 @@ struct sqlite3_io_methods { ** additional information. ** **
  • [[SQLITE_FCNTL_SYNC_OMITTED]] -** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by -** SQLite and sent to all VFSes in place of a call to the xSync method -** when the database connection has [PRAGMA synchronous] set to OFF.)^ -** Some specialized VFSes need this signal in order to operate correctly -** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most -** VFSes do not need this signal and should silently ignore this opcode. -** Applications should not call [sqlite3_file_control()] with this -** opcode as doing so may disrupt the operation of the specialized VFSes -** that do require it. +** No longer in use. +** +**
  • [[SQLITE_FCNTL_SYNC]] +** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and +** sent to the VFS immediately before the xSync method is invoked on a +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** of the xSync method. In most cases, the pointer argument passed with +** this file-control is NULL. However, if the database file is being synced +** as part of a multi-database commit, the argument points to a nul-terminated +** string containing the transactions master-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] +** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite +** and sent to the VFS after a transaction has been committed immediately +** but before the database is unlocked. VFSes that do not need this signal +** should silently ignore this opcode. Applications should not call +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. ** **
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic @@ -921,6 +937,12 @@ struct sqlite3_io_methods { ** SQLite stack may generate instances of this file control if ** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. ** +**
  • [[SQLITE_FCNTL_HAS_MOVED]] +** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a +** pointer to an integer and it writes a boolean into that integer depending +** on whether or not the file has been renamed, moved, or deleted since it +** was first opened. +** ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -941,6 +963,9 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_TEMPFILENAME 16 #define SQLITE_FCNTL_MMAP_SIZE 18 #define SQLITE_FCNTL_TRACE 19 +#define SQLITE_FCNTL_HAS_MOVED 20 +#define SQLITE_FCNTL_SYNC 21 +#define SQLITE_FCNTL_COMMIT_PHASETWO 22 /* ** CAPI3REF: Mutex Handle @@ -2375,11 +2400,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. +** ^If N is less than one, then P can be a NULL pointer. ** -** ^The first time this routine is invoked (either internally or by -** the application) the PRNG is seeded using randomness obtained -** from the xRandomness method of the default [sqlite3_vfs] object. -** ^On all subsequent invocations, the pseudo-randomness is generated +** ^If this routine has not been previously called or if the previous +** call had N less than one, then the PRNG is seeded using randomness +** obtained from the xRandomness method of the default [sqlite3_vfs] object. +** ^If the previous call to this routine had an N of 1 or more then +** the pseudo-randomness is generated ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ @@ -2539,6 +2566,7 @@ SQLITE_API int sqlite3_set_authorizer( #define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ +#define SQLITE_RECURSIVE 33 /* NULL NULL */ /* ** CAPI3REF: Tracing And Profiling Functions @@ -3957,15 +3985,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); ** ** ^The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Every SQL function implementation must be able to work -** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. ^An application may -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. +** its parameters. The application should set this parameter to +** [SQLITE_UTF16LE] if the function implementation invokes +** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the +** implementation invokes [sqlite3_value_text16be()] on an input, or +** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] +** otherwise. ^The same SQL function may be registered multiple times using +** different preferred text encodings, with different implementations for +** each encoding. ** ^When multiple implementations of the same function are available, SQLite ** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what text -** encoding is used, then the fourth argument should be [SQLITE_ANY]. +** +** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC] +** to signal that the function will always return the same result given +** the same inputs within a single SQL statement. Most SQL functions are +** deterministic. The built-in [random()] SQL function is an example of a +** function that is not deterministic. The SQLite query planner is able to +** perform additional optimizations on deterministic functions, so use +** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ @@ -4051,9 +4088,19 @@ SQLITE_API int sqlite3_create_function_v2( #define SQLITE_UTF16LE 2 #define SQLITE_UTF16BE 3 #define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ +/* +** CAPI3REF: Function Flags +** +** These constants may be ORed together with the +** [SQLITE_UTF8 | preferred text encoding] as the fourth argument +** to [sqlite3_create_function()], [sqlite3_create_function16()], or +** [sqlite3_create_function_v2()]. +*/ +#define SQLITE_DETERMINISTIC 0x800 + /* ** CAPI3REF: Deprecated Functions ** DEPRECATED @@ -6075,7 +6122,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 -#define SQLITE_TESTCTRL_LAST 20 +#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 +#define SQLITE_TESTCTRL_LAST 21 /* ** CAPI3REF: SQLite Runtime Status -- cgit v1.2.3 From 0d50efeae9829336ffb7e47692cfdc649e10ee70 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 18 Mar 2014 12:07:53 +0100 Subject: Fix QByteArray memory corruption in QIBaseDriver::open(). Rewrite code to use QByteArray::reserve(), QByteArray::append() instead of memcpy(). Task-number: QTBUG-37508 Change-Id: I16ead153f33fa5a34bc01ee27ae4cd1b8993b65e Reviewed-by: Andy Shaw Reviewed-by: Mark Brand --- src/sql/drivers/ibase/qsql_ibase.cpp | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index fe5a3cd23a..d50078b5ff 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1490,27 +1490,22 @@ bool QIBaseDriver::open(const QString & db, pass.truncate(255); QByteArray ba; - ba.resize(usr.length() + pass.length() + enc.length() + role.length() + 6); - int i = -1; - ba[++i] = isc_dpb_version1; - ba[++i] = isc_dpb_user_name; - ba[++i] = usr.length(); - memcpy(ba.data() + ++i, usr.data(), usr.length()); - i += usr.length(); - ba[i] = isc_dpb_password; - ba[++i] = pass.length(); - memcpy(ba.data() + ++i, pass.data(), pass.length()); - i += pass.length(); - ba[i] = isc_dpb_lc_ctype; - ba[++i] = enc.length(); - memcpy(ba.data() + ++i, enc.data(), enc.length()); - i += enc.length(); + ba.reserve(usr.length() + pass.length() + enc.length() + role.length() + 9); + ba.append(char(isc_dpb_version1)); + ba.append(char(isc_dpb_user_name)); + ba.append(char(usr.length())); + ba.append(usr.data(), usr.length()); + ba.append(char(isc_dpb_password)); + ba.append(char(pass.length())); + ba.append(pass.data(), pass.length()); + ba.append(char(isc_dpb_lc_ctype)); + ba.append(char(enc.length())); + ba.append(enc.data(), enc.length()); if (!role.isEmpty()) { - ba[i] = isc_dpb_sql_role_name; - ba[++i] = role.length(); - memcpy(ba.data() + ++i, role.data(), role.length()); - i += role.length(); + ba.append(char(isc_dpb_sql_role_name)); + ba.append(char(role.length())); + ba.append(role.data(), role.length()); } QString portString; @@ -1522,7 +1517,7 @@ bool QIBaseDriver::open(const QString & db, ldb += host + portString + QLatin1Char(':'); ldb += db; isc_attach_database(d->status, 0, const_cast(ldb.toLocal8Bit().constData()), - &d->ibase, i, ba.data()); + &d->ibase, ba.size(), ba.data()); if (d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Error opening database"), QSqlError::ConnectionError)) { setOpenError(true); -- cgit v1.2.3 From c6b555dac389f9a599a9ad342de56dea329fff60 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 15 Mar 2014 15:55:36 +0200 Subject: Fix bundled HarfBuzz-NG build outside QtGui On Mac, hb_coretext requires both CTFont and CGFont. Due to not supporting the 0 tag by CoreText, hb_blob_get_data() always fails causing the hb_coretext_shaper initialization to fail, too. Since HarfBuzz-NG is not a part of QtGui module anymore, there are two possibilities to workaround this: either engineer the font data by querying tables one-by-one and generating the font directory table, or pass CTFont and CGFont refs directly to hb_coretext via the hb_face's user_data. This patch implements the latter. Change-Id: I7d2e2df00818ea811642cb6a6c3b9c9abd5d7b94 Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz-ng/src/hb-coretext.cc | 46 +++++++++++----------- .../fontdatabases/mac/qfontengine_coretext.mm | 31 ++++++++++----- 2 files changed, 45 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc index 5a34eddecc..40c06371bd 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc @@ -32,7 +32,6 @@ #include "hb-coretext.h" #include "hb-face-private.hh" -#include #ifndef HB_DEBUG_CORETEXT @@ -44,6 +43,19 @@ HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) +typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length); + +struct FontEngineFaceData { + void *user_data; + qt_get_font_table_func_t get_font_table; +}; + +struct CoreTextFontEngineData { + CTFontRef ctFont; + CGFontRef cgFont; +}; + + /* * shaper face data */ @@ -83,25 +95,11 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) if (unlikely (!data)) return NULL; - QFontEngine *fe = (QFontEngine *) ((QFontEngine::FaceData *) face->user_data)->user_data; - if (fe->type () == QFontEngine::Mac) - { - data->cg_font = (CGFontRef) fe->userData ().value (); - if (likely (data->cg_font)) - CFRetain (data->cg_font); - } - else - { - hb_blob_t *blob = hb_face_reference_blob (face); - unsigned int blob_length; - const char *blob_data = hb_blob_get_data (blob, &blob_length); - if (unlikely (!blob_length)) - DEBUG_MSG (CORETEXT, face, "Face has empty blob"); - - CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); - data->cg_font = CGFontCreateWithDataProvider (provider); - CGDataProviderRelease (provider); - } + FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data; + CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data; + data->cg_font = coreTextFontEngineData->cgFont; + if (likely (data->cg_font)) + CFRetain (data->cg_font); if (unlikely (!data->cg_font)) { DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); @@ -146,9 +144,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) return NULL; hb_face_t *face = font->face; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale / 64, NULL, NULL); + FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data; + CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data; + data->ct_font = coreTextFontEngineData->ctFont; + if (likely (data->ct_font)) + CFRetain (data->ct_font); + if (unlikely (!data->ct_font)) { DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); free (data); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 3c30df6efb..0460f11139 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -50,6 +50,22 @@ QT_BEGIN_NAMESPACE static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); +static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length) +{ + CTFontRef ctfont = *(CTFontRef *)user_data; + + QCFType table = CTFontCopyTable(ctfont, tag, 0); + if (!table) + return false; + + CFIndex tableLength = CFDataGetLength(table); + if (buffer && int(*length) >= tableLength) + CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer); + *length = tableLength; + Q_ASSERT(int(*length) > 0); + return true; +} + static void loadAdvancesForGlyphs(CTFontRef ctfont, QVarLengthArray &cgGlyphs, QGlyphLayout *glyphs, int len, @@ -191,7 +207,10 @@ void QCoreTextFontEngine::init() cache_cost = (CTFontGetAscent(ctfont) + CTFontGetDescent(ctfont)) * avgCharWidth.toInt() * 2000; - setUserData(QVariant::fromValue((void *)cgFont)); + // HACK hb_coretext requires both CTFont and CGFont but user_data is only void* + Q_ASSERT((void *)(&ctfont + 1) == (void *)&cgFont); + faceData.user_data = &ctfont; + faceData.get_font_table = ct_getSfntTable; } glyph_t QCoreTextFontEngine::glyphIndex(uint ucs4) const @@ -683,15 +702,7 @@ bool QCoreTextFontEngine::canRender(const QChar *string, int len) const bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const { - QCFType table = CTFontCopyTable(ctfont, tag, 0); - if (!table) - return false; - CFIndex tableLength = CFDataGetLength(table); - if (buffer && int(*length) >= tableLength) - CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer); - *length = tableLength; - Q_ASSERT(int(*length) > 0); - return true; + return ct_getSfntTable((void *)&ctfont, tag, buffer, length); } void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *) -- cgit v1.2.3 From b19b0808940c8c54b102012be134a370b26e348e Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 5 Feb 2014 16:25:06 +0100 Subject: Update bundled libxkbcommon version to 0.4.0 This release comes with important bug fixes. Also we can now remove the workaround code which was needed for libxkbcommon 0.2.0. Task-number: QTBUG-31712 Task-number: QTBUG-33732 Task-number: QTBUG-34056 Change-Id: I57caf7f803b9a01a15541a5ad82e464de3b8abbb Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll --- src/3rdparty/xkbcommon.pri | 34 +- src/3rdparty/xkbcommon/NEWS | 86 + src/3rdparty/xkbcommon/README | 47 +- src/3rdparty/xkbcommon/src/atom.c | 137 +- src/3rdparty/xkbcommon/src/atom.h | 7 +- src/3rdparty/xkbcommon/src/context-priv.c | 171 + src/3rdparty/xkbcommon/src/context.c | 179 +- src/3rdparty/xkbcommon/src/context.h | 62 +- src/3rdparty/xkbcommon/src/keymap-priv.c | 121 + src/3rdparty/xkbcommon/src/keymap.h | 29 +- src/3rdparty/xkbcommon/src/keysym-utf.c | 13 +- src/3rdparty/xkbcommon/src/keysym.c | 56 +- src/3rdparty/xkbcommon/src/keysym.h | 6 + src/3rdparty/xkbcommon/src/ks_tables.h | 11765 +++++++++++-------- src/3rdparty/xkbcommon/src/state.c | 20 +- src/3rdparty/xkbcommon/src/text.c | 8 +- src/3rdparty/xkbcommon/src/utils.c | 107 + src/3rdparty/xkbcommon/src/utils.h | 95 + src/3rdparty/xkbcommon/src/x11/util.c | 215 + src/3rdparty/xkbcommon/src/x11/x11-keymap.c | 1146 ++ src/3rdparty/xkbcommon/src/x11/x11-priv.h | 54 + src/3rdparty/xkbcommon/src/x11/x11-state.c | 71 + src/3rdparty/xkbcommon/src/xkb-keymap.c | 135 +- src/3rdparty/xkbcommon/src/xkbcomp/action.c | 91 +- src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c | 318 +- src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h | 58 +- src/3rdparty/xkbcommon/src/xkbcomp/ast.h | 124 +- src/3rdparty/xkbcommon/src/xkbcomp/compat.c | 61 +- src/3rdparty/xkbcommon/src/xkbcomp/expr.c | 170 +- src/3rdparty/xkbcommon/src/xkbcomp/include.c | 36 +- src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c | 29 +- src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c | 22 +- src/3rdparty/xkbcommon/src/xkbcomp/keymap.c | 30 +- src/3rdparty/xkbcommon/src/xkbcomp/keywords.c | 349 + src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h | 15 +- src/3rdparty/xkbcommon/src/xkbcomp/parser.c | 738 +- src/3rdparty/xkbcommon/src/xkbcomp/parser.h | 18 +- src/3rdparty/xkbcommon/src/xkbcomp/rules.c | 243 +- src/3rdparty/xkbcommon/src/xkbcomp/scanner-utils.h | 145 + src/3rdparty/xkbcommon/src/xkbcomp/scanner.c | 2990 +---- src/3rdparty/xkbcommon/src/xkbcomp/symbols.c | 122 +- src/3rdparty/xkbcommon/src/xkbcomp/types.c | 13 +- src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-priv.h | 12 +- src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp.c | 38 +- .../xkbcommon/xkbcommon/xkbcommon-keysyms.h | 8 + src/3rdparty/xkbcommon/xkbcommon/xkbcommon-names.h | 1 + src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h | 166 + src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h | 187 +- .../xkbcommon/xkbcommon/xkbcommon_workaround.h | 105 - .../platforminputcontexts/compose/compose.pro | 8 +- .../compose/generator/qtablegenerator.cpp | 20 - .../platforminputcontexts.pro | 5 +- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 20 - src/plugins/platforms/xcb/xcb-plugin.pro | 5 +- 54 files changed, 11387 insertions(+), 9324 deletions(-) create mode 100644 src/3rdparty/xkbcommon/NEWS create mode 100644 src/3rdparty/xkbcommon/src/context-priv.c create mode 100644 src/3rdparty/xkbcommon/src/keymap-priv.c create mode 100644 src/3rdparty/xkbcommon/src/utils.c create mode 100644 src/3rdparty/xkbcommon/src/x11/util.c create mode 100644 src/3rdparty/xkbcommon/src/x11/x11-keymap.c create mode 100644 src/3rdparty/xkbcommon/src/x11/x11-priv.h create mode 100644 src/3rdparty/xkbcommon/src/x11/x11-state.c create mode 100644 src/3rdparty/xkbcommon/src/xkbcomp/keywords.c create mode 100644 src/3rdparty/xkbcommon/src/xkbcomp/scanner-utils.h create mode 100644 src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h delete mode 100644 src/3rdparty/xkbcommon/xkbcommon/xkbcommon_workaround.h (limited to 'src') diff --git a/src/3rdparty/xkbcommon.pri b/src/3rdparty/xkbcommon.pri index 57470c0499..eb34403746 100644 --- a/src/3rdparty/xkbcommon.pri +++ b/src/3rdparty/xkbcommon.pri @@ -1,15 +1,20 @@ QMAKE_CFLAGS += -std=gnu99 -w -INCLUDEPATH += $$PWD/xkbcommon $$PWD/xkbcommon/src $$PWD/xkbcommon/src/xkbcomp +INCLUDEPATH += $$PWD/xkbcommon \ + $$PWD/xkbcommon/xkbcommon \ + $$PWD/xkbcommon/src \ + $$PWD/xkbcommon/src/xkbcomp DEFINES += DFLT_XKB_CONFIG_ROOT='\\"$$QMAKE_XKB_CONFIG_ROOT\\"' -### RMLVO names can be overwritten with environmental variables (See libxkbcommon documentation) +### RMLVO names can be overwritten with environmental variables (see libxkbcommon documentation) DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"' DEFINES += DEFAULT_XKB_MODEL='\\"pc105\\"' DEFINES += DEFAULT_XKB_LAYOUT='\\"us\\"' +# Need to rename several files, qmake has problems processing a project when +# sub-directories contain files with an equal names. -# Need to rename 2 files, qmake has problems processing a project when -# directories contain files with equal names. +# libxkbcommon generates some of these files while executing "./autogen.sh" +# and some while executing "make" (actually YACC) SOURCES += \ $$PWD/xkbcommon/src/atom.c \ $$PWD/xkbcommon/src/xkb-compat.c \ # renamed: compat.c -> xkb-compat.c @@ -18,7 +23,10 @@ SOURCES += \ $$PWD/xkbcommon/src/keysym.c \ $$PWD/xkbcommon/src/keysym-utf.c \ $$PWD/xkbcommon/src/state.c \ - $$PWD/xkbcommon/src/text.c + $$PWD/xkbcommon/src/text.c \ + $$PWD/xkbcommon/src/context-priv.c \ + $$PWD/xkbcommon/src/keymap-priv.c \ + $$PWD/xkbcommon/src/utils.c SOURCES += \ $$PWD/xkbcommon/src/xkbcomp/action.c \ @@ -29,12 +37,24 @@ SOURCES += \ $$PWD/xkbcommon/src/xkbcomp/keycodes.c \ $$PWD/xkbcommon/src/xkbcomp/keymap-dump.c \ $$PWD/xkbcommon/src/xkbcomp/keymap.c \ - $$PWD/xkbcommon/src/xkbcomp/parser.c \ + $$PWD/xkbcommon/src/xkbcomp/keywords.c \ $$PWD/xkbcommon/src/xkbcomp/rules.c \ $$PWD/xkbcommon/src/xkbcomp/scanner.c \ $$PWD/xkbcommon/src/xkbcomp/symbols.c \ $$PWD/xkbcommon/src/xkbcomp/types.c \ $$PWD/xkbcommon/src/xkbcomp/vmod.c \ - $$PWD/xkbcommon/src/xkbcomp/xkbcomp.c + $$PWD/xkbcommon/src/xkbcomp/xkbcomp.c \ + $$PWD/xkbcommon/src/xkbcomp/parser.c + +!contains(DEFINES, QT_NO_XKB):contains(QT_CONFIG, use-xkbcommon-x11support): { + # Build xkbcommon-x11 support library, it depends on -lxcb and -lxcb-xkb, linking is done + # in xcb-plugin.pro (linked to system libraries or if Qt was configured with -qt-xcb then + # linked to -lxcb-static). + INCLUDEPATH += $$PWD/xkbcommon/src/x11 + SOURCES += \ + $$PWD/xkbcommon/src/x11/util.c \ + $$PWD/xkbcommon/src/x11/x11-keymap.c \ # renamed: keymap.c -> x11-keymap.c + $$PWD/xkbcommon/src/x11/x11-state.c # renamed: state.c -> x11-keymap.c +} TR_EXCLUDE += $$PWD/* diff --git a/src/3rdparty/xkbcommon/NEWS b/src/3rdparty/xkbcommon/NEWS new file mode 100644 index 0000000000..450b7535ee --- /dev/null +++ b/src/3rdparty/xkbcommon/NEWS @@ -0,0 +1,86 @@ +libxkbcommon 0.4.0 +================== + +- Add a new add-on library, xkbcommon-x11, to support creating keymaps + with the XKB X11 protocol, by querying the X server directly. + See the xkbcommon/xkbcommon-x11.h header file for more details. + This library requires libxcb-xkb >= 1.10, and is enabled by default. + It can be disabled with the --disable-x11 configure switch. + Distributions are encouraged to split the necessary files for this + library (libxkbcommon-x11.so, xkbcommon-x11.pc, xkbcommon/xkbcommon-x11.h) + to a separate package, such that the main package does not depend on + X11 libraries. + +- Fix the keysym <-> name lookup table to not require huge amounts of + relocations. + +- Fix a bug in the keysym <-> name lookup, whereby lookup might fail in + some rare cases. + +- Reduce memory usage during keymap compilation. + +- New API: + New keysyms from xproto 7.0.25 (German T3 layout keysyms). + XKB_MOD_NAME_NUM for the usual NumLock modifier. + xkb_x11_* types and functions, XKB_X11_* constants. + + +libxkbcommon 0.3.2 +================== + +- Log messages from the library now look like "xkbcommon: ERROR" by + default, instead of xkbcomp-like "Error: ". + +- Apply capitalization transformation on keysyms in + xkb_keysym_get_one_sym(), to match the behavior specified in the XKB + specification: + http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier + +- Support byacc for generating the parser, in addition to Bison. + +- New API: + XKB_KEY_XF86AudioMicMute keysym from xproto 7.0.24. + XKB_KEYSYM_NO_FLAGS + XKB_CONTEXT_NO_FLAGS + XKB_MAP_COMPILE_NO_FLAGS + +- Bug fixes. + + +libxkbcommon 0.3.1 +================== + +- Replace the flex scanner with a hand-written one. flex is no longer + a build requirement. + +- New API: + xkb_keymap_min_keycode() + xkb_keymap_max_keycode() + xkb_keymap_key_for_each() + + +libxkbcommon 0.3.0 +================== + +- Allow passing NULL to *_unref() functions; do nothing instead of + crashing. + +- The functions xkb_keymap_num_levels_for_key() and + xkb_keymap_get_syms_by_level() now allow out-of-range values for the + 'layout' parameter. The functions now wrap the value around the number + of layouts instead of failing. + +- The function xkb_keysym_get_name() now types unicode keysyms in + uppercase and 0-padding, to match the format used by XKeysymToString(). + +- Building Linux-specific tests is no longer attempted on non-Linux + environments. + +- The function xkb_keymap_new_from_names() now accepts a NULL value for + the 'names' parameter, instead of failing. This is equivalent to passing + a 'struct xkb_rule_names' with all fields set to NULL. + +- New API: + xkb_keymap_new_from_buffer() + +- Bug fixes. diff --git a/src/3rdparty/xkbcommon/README b/src/3rdparty/xkbcommon/README index fa8e94c81c..6b99c46620 100644 --- a/src/3rdparty/xkbcommon/README +++ b/src/3rdparty/xkbcommon/README @@ -25,27 +25,17 @@ API While xkbcommon's API is somewhat derived from the classic XKB API as found in and friends, it has been substantially reworked to -expose fewer internal details to clients. The only supported API is available -in . Any definition not in this header (including -accessing internal structures through the old macros previously available) -should be regarded as an implementation detail and is liable to change at any -time. +expose fewer internal details to clients. The supported API is available +in the files. Additional support is provided for +X11 (XCB) clients, in the xkbcommon-x11 library, . -During its early development, xkbcommon does not promise API or ABI stability. -Regardless, we will attempt to not break ABI during a minor release series, -so applications written against 0.1.0 should be completely compatible with -0.1.3, but not necessarily with 0.2.0. However, new symbols may be introduced -in any release. Thus, anyone packaging xkbcommon should make sure any package -depending on it depends on a release greater than or equal to the version it -was built against (or earlier, if it doesn't use any newly-introduced -symbols), but less than the next major release. - -xkbcommon 1.x will offer full API and ABI stability for its lifetime, with a -soname of libxkbcommon.so.1. Any ABI breaks will wait until xkbcommon 2.0, -which will be libxkbcommon.so.2. - -The xkbcomp command-line tool has also been removed, although this will -likely reappear in a later release. +The xkbcommon API and ABI are stable. We will attempt to not break ABI during +a minor release series, so applications written against 0.1.0 should be +completely compatible with 0.5.3, but not necessarily with 1.0.0. However, new +symbols may be introduced in any release. Thus, anyone packaging xkbcommon +should make sure any package depending on it depends on a release greater than +or equal to the version it was built against (or earlier, if it doesn't use +any newly-introduced symbols), but less than the next major release. Relation to X11 @@ -101,19 +91,24 @@ Development An extremely rudimentary homepage can be found at: http://xkbcommon.org -xkbcommon is maintained in git at freedesktop.org: - git://anongit.freedesktop.org/git/libxkbcommon +xkbcommon is maintained in git at github.com: + https://github.com/xkbcommon/libxkbcommon Patches are always welcome, and may be sent to either xorg-devel@lists.x.org, -or wayland-devel@lists.freedesktop.org. Bugs are tracked in Bugzilla at: - http://bugs.freedesktop.org +or wayland-devel@lists.freedesktop.org. + +Bugs are tracked in Bugzilla at: + https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon +Or in github at: + https://github.com/xkbcommon/libxkbcommon/issues -The maintainer is Daniel Stone, who can be reached at: +The maintainers are Daniel Stone and Ran Benita, who can be reached at: + Credits ======= Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon -off the ground initially, as well as to Ran Benita for subsequent development. +off the ground initially. diff --git a/src/3rdparty/xkbcommon/src/atom.c b/src/3rdparty/xkbcommon/src/atom.c index a77502336e..044f56681a 100644 --- a/src/3rdparty/xkbcommon/src/atom.c +++ b/src/3rdparty/xkbcommon/src/atom.c @@ -74,15 +74,15 @@ #include "atom.h" struct atom_node { - struct atom_node *left, *right; + xkb_atom_t left, right; xkb_atom_t atom; unsigned int fingerprint; char *string; }; struct atom_table { - struct atom_node *root; - darray(struct atom_node *) table; + xkb_atom_t root; + darray(struct atom_node) table; }; struct atom_table * @@ -95,31 +95,22 @@ atom_table_new(void) return NULL; darray_init(table->table); - darray_growalloc(table->table, 100); - darray_append(table->table, NULL); + /* The original throw-away root is here, at the illegal atom 0. */ + darray_resize0(table->table, 1); return table; } -static void -free_atom(struct atom_node *patom) -{ - if (!patom) - return; - - free_atom(patom->left); - free_atom(patom->right); - free(patom->string); - free(patom); -} - void atom_table_free(struct atom_table *table) { + struct atom_node *node; + if (!table) return; - free_atom(table->root); + darray_foreach(node, table->table) + free(node->string); darray_free(table->table); free(table); } @@ -127,52 +118,42 @@ atom_table_free(struct atom_table *table) const char * atom_text(struct atom_table *table, xkb_atom_t atom) { - if (atom >= darray_size(table->table) || - darray_item(table->table, atom) == NULL) + if (atom == XKB_ATOM_NONE || atom >= darray_size(table->table)) return NULL; - return darray_item(table->table, atom)->string; -} - -char * -atom_strdup(struct atom_table *table, xkb_atom_t atom) -{ - return strdup_safe(atom_text(table, atom)); + return darray_item(table->table, atom).string; } static bool -find_node_pointer(struct atom_table *table, const char *string, - struct atom_node ***np_out, unsigned int *fingerprint_out) +find_atom_pointer(struct atom_table *table, const char *string, size_t len, + xkb_atom_t **atomp_out, unsigned int *fingerprint_out) { - struct atom_node **np; - unsigned i; - int comp; - unsigned int fp = 0; - size_t len; + xkb_atom_t *atomp = &table->root; + unsigned int fingerprint = 0; bool found = false; - len = strlen(string); - np = &table->root; - for (i = 0; i < (len + 1) / 2; i++) { - fp = fp * 27 + string[i]; - fp = fp * 27 + string[len - 1 - i]; + for (size_t i = 0; i < (len + 1) / 2; i++) { + fingerprint = fingerprint * 27 + string[i]; + fingerprint = fingerprint * 27 + string[len - 1 - i]; } - while (*np) { - if (fp < (*np)->fingerprint) { - np = &((*np)->left); + while (*atomp != XKB_ATOM_NONE) { + struct atom_node *node = &darray_item(table->table, *atomp); + + if (fingerprint < node->fingerprint) { + atomp = &node->left; } - else if (fp > (*np)->fingerprint) { - np = &((*np)->right); + else if (fingerprint > node->fingerprint) { + atomp = &node->right; } else { - /* now start testing the strings */ - comp = strncmp(string, (*np)->string, len); - if (comp < 0 || (comp == 0 && len < strlen((*np)->string))) { - np = &((*np)->left); + /* Now start testing the strings. */ + const int cmp = strncmp(string, node->string, len); + if (cmp < 0 || (cmp == 0 && len < strlen(node->string))) { + atomp = &node->left; } - else if (comp > 0) { - np = &((*np)->right); + else if (cmp > 0) { + atomp = &node->right; } else { found = true; @@ -181,68 +162,64 @@ find_node_pointer(struct atom_table *table, const char *string, } } - *fingerprint_out = fp; - *np_out = np; + if (fingerprint_out) + *fingerprint_out = fingerprint; + if (atomp_out) + *atomp_out = atomp; return found; } xkb_atom_t -atom_lookup(struct atom_table *table, const char *string) +atom_lookup(struct atom_table *table, const char *string, size_t len) { - struct atom_node **np; - unsigned int fp; + xkb_atom_t *atomp; if (!string) return XKB_ATOM_NONE; - if (!find_node_pointer(table, string, &np, &fp)) + if (!find_atom_pointer(table, string, len, &atomp, NULL)) return XKB_ATOM_NONE; - return (*np)->atom; + return *atomp; } /* * If steal is true, we do not strdup @string; therefore it must be - * dynamically allocated, not be free'd by the caller and not be used - * afterwards. Use to avoid some redundant allocations. + * dynamically allocated, NUL-terminated, not be free'd by the caller + * and not be used afterwards. Use to avoid some redundant allocations. */ xkb_atom_t -atom_intern(struct atom_table *table, const char *string, +atom_intern(struct atom_table *table, const char *string, size_t len, bool steal) { - struct atom_node **np; - struct atom_node *nd; - unsigned int fp; + xkb_atom_t *atomp; + struct atom_node node; + unsigned int fingerprint; if (!string) return XKB_ATOM_NONE; - if (find_node_pointer(table, string, &np, &fp)) { + if (find_atom_pointer(table, string, len, &atomp, &fingerprint)) { if (steal) free(UNCONSTIFY(string)); - return (*np)->atom; + return *atomp; } - nd = malloc(sizeof(*nd)); - if (!nd) - return XKB_ATOM_NONE; - if (steal) { - nd->string = UNCONSTIFY(string); + node.string = UNCONSTIFY(string); } else { - nd->string = strdup(string); - if (!nd->string) { - free(nd); + node.string = strndup(string, len); + if (!node.string) return XKB_ATOM_NONE; - } } - *np = nd; - nd->left = nd->right = NULL; - nd->fingerprint = fp; - nd->atom = darray_size(table->table); - darray_append(table->table, nd); + node.left = node.right = XKB_ATOM_NONE; + node.fingerprint = fingerprint; + node.atom = darray_size(table->table); + /* Do this before the append, as it may realloc and change the offsets. */ + *atomp = node.atom; + darray_append(table->table, node); - return nd->atom; + return node.atom; } diff --git a/src/3rdparty/xkbcommon/src/atom.h b/src/3rdparty/xkbcommon/src/atom.h index f1abf1b72f..1bf8e49b8e 100644 --- a/src/3rdparty/xkbcommon/src/atom.h +++ b/src/3rdparty/xkbcommon/src/atom.h @@ -37,15 +37,12 @@ void atom_table_free(struct atom_table *table); xkb_atom_t -atom_lookup(struct atom_table *table, const char *string); +atom_lookup(struct atom_table *table, const char *string, size_t len); xkb_atom_t -atom_intern(struct atom_table *table, const char *string, +atom_intern(struct atom_table *table, const char *string, size_t len, bool steal); -char * -atom_strdup(struct atom_table *table, xkb_atom_t atom); - const char * atom_text(struct atom_table *table, xkb_atom_t atom); diff --git a/src/3rdparty/xkbcommon/src/context-priv.c b/src/3rdparty/xkbcommon/src/context-priv.c new file mode 100644 index 0000000000..4d7b2ed110 --- /dev/null +++ b/src/3rdparty/xkbcommon/src/context-priv.c @@ -0,0 +1,171 @@ +/* + * Copyright © 2012 Intel Corporation + * Copyright © 2012 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone + */ + +#include +#include +#include +#include + +#include "xkbcommon/xkbcommon.h" +#include "utils.h" +#include "context.h" + +unsigned int +xkb_context_num_failed_include_paths(struct xkb_context *ctx) +{ + return darray_size(ctx->failed_includes); +} + +const char * +xkb_context_failed_include_path_get(struct xkb_context *ctx, + unsigned int idx) +{ + if (idx >= xkb_context_num_failed_include_paths(ctx)) + return NULL; + + return darray_item(ctx->failed_includes, idx); +} + +xkb_atom_t +xkb_atom_lookup(struct xkb_context *ctx, const char *string) +{ + return atom_lookup(ctx->atom_table, string, strlen(string)); +} + +xkb_atom_t +xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len) +{ + return atom_intern(ctx->atom_table, string, len, false); +} + +xkb_atom_t +xkb_atom_steal(struct xkb_context *ctx, char *string) +{ + return atom_intern(ctx->atom_table, string, strlen(string), true); +} + +const char * +xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom) +{ + return atom_text(ctx->atom_table, atom); +} + +void +xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity, + const char *fmt, ...) +{ + va_list args; + + if (ctx->log_level < level || ctx->log_verbosity < verbosity) + return; + + va_start(args, fmt); + ctx->log_fn(ctx, level, fmt, args); + va_end(args); +} + +char * +xkb_context_get_buffer(struct xkb_context *ctx, size_t size) +{ + char *rtrn; + + if (size >= sizeof(ctx->text_buffer)) + return NULL; + + if (sizeof(ctx->text_buffer) - ctx->text_next <= size) + ctx->text_next = 0; + + rtrn = &ctx->text_buffer[ctx->text_next]; + ctx->text_next += size; + + return rtrn; +} + +#ifndef DEFAULT_XKB_VARIANT +#define DEFAULT_XKB_VARIANT NULL +#endif + +#ifndef DEFAULT_XKB_OPTIONS +#define DEFAULT_XKB_OPTIONS NULL +#endif + +const char * +xkb_context_get_default_rules(struct xkb_context *ctx) +{ + const char *env = NULL; + + if (ctx->use_environment_names) + env = getenv("XKB_DEFAULT_RULES"); + + return env ? env : DEFAULT_XKB_RULES; +} + +const char * +xkb_context_get_default_model(struct xkb_context *ctx) +{ + const char *env = NULL; + + if (ctx->use_environment_names) + env = getenv("XKB_DEFAULT_MODEL"); + + return env ? env : DEFAULT_XKB_MODEL; +} + +const char * +xkb_context_get_default_layout(struct xkb_context *ctx) +{ + const char *env = NULL; + + if (ctx->use_environment_names) + env = getenv("XKB_DEFAULT_LAYOUT"); + + return env ? env : DEFAULT_XKB_LAYOUT; +} + +const char * +xkb_context_get_default_variant(struct xkb_context *ctx) +{ + const char *env = NULL; + const char *layout = getenv("XKB_DEFAULT_VARIANT"); + + /* We don't want to inherit the variant if they haven't also set a + * layout, since they're so closely paired. */ + if (layout && ctx->use_environment_names) + env = getenv("XKB_DEFAULT_VARIANT"); + + return env ? env : DEFAULT_XKB_VARIANT; +} + +const char * +xkb_context_get_default_options(struct xkb_context *ctx) +{ + const char *env = NULL; + + if (ctx->use_environment_names) + env = getenv("XKB_DEFAULT_OPTIONS"); + + return env ? env : DEFAULT_XKB_OPTIONS; +} diff --git a/src/3rdparty/xkbcommon/src/context.c b/src/3rdparty/xkbcommon/src/context.c index 8d56487004..e64b91542f 100644 --- a/src/3rdparty/xkbcommon/src/context.c +++ b/src/3rdparty/xkbcommon/src/context.c @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -34,30 +33,6 @@ #include "utils.h" #include "context.h" -struct xkb_context { - int refcnt; - - ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx, - enum xkb_log_level level, - const char *fmt, va_list args); - enum xkb_log_level log_level; - int log_verbosity; - void *user_data; - - struct xkb_rule_names names_dflt; - - darray(char *) includes; - darray(char *) failed_includes; - - struct atom_table *atom_table; - - /* Buffer for the *Text() functions. */ - char text_buffer[2048]; - size_t text_next; - - unsigned int use_environment_names : 1; -}; - /** * Append one directory to the context's include path. */ @@ -155,12 +130,6 @@ xkb_context_num_include_paths(struct xkb_context *ctx) return darray_size(ctx->includes); } -unsigned int -xkb_context_num_failed_include_paths(struct xkb_context *ctx) -{ - return darray_size(ctx->failed_includes); -} - /** * Returns the given entry in the context's include path, or NULL if an * invalid index is passed. @@ -174,16 +143,6 @@ xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx) return darray_item(ctx->includes, idx); } -const char * -xkb_context_failed_include_path_get(struct xkb_context *ctx, - unsigned int idx) -{ - if (idx >= xkb_context_num_failed_include_paths(ctx)) - return NULL; - - return darray_item(ctx->failed_includes, idx); -} - /** * Take a new reference on the context. */ @@ -214,15 +173,15 @@ log_level_to_prefix(enum xkb_log_level level) { switch (level) { case XKB_LOG_LEVEL_DEBUG: - return "Debug:"; + return "xkbcommon: DEBUG: "; case XKB_LOG_LEVEL_INFO: - return "Info:"; + return "xkbcommon: INFO: "; case XKB_LOG_LEVEL_WARNING: - return "Warning:"; + return "xkbcommon: WARNING: "; case XKB_LOG_LEVEL_ERROR: - return "Error:"; + return "xkbcommon: ERROR: "; case XKB_LOG_LEVEL_CRITICAL: - return "Critical:"; + return "xkbcommon: CRITICAL: "; default: return NULL; } @@ -235,7 +194,7 @@ default_log_fn(struct xkb_context *ctx, enum xkb_log_level level, const char *prefix = log_level_to_prefix(level); if (prefix) - fprintf(stderr, "%-10s", prefix); + fprintf(stderr, "%s", prefix); vfprintf(stderr, fmt, args); } @@ -246,7 +205,7 @@ log_level(const char *level) { errno = 0; lvl = strtol(level, &endptr, 10); - if (errno == 0 && (endptr[0] == '\0' || isspace(endptr[0]))) + if (errno == 0 && (endptr[0] == '\0' || is_space(endptr[0]))) return lvl; if (istreq_prefix("crit", level)) return XKB_LOG_LEVEL_CRITICAL; @@ -275,14 +234,6 @@ log_verbosity(const char *verbosity) { return 0; } -#ifndef DEFAULT_XKB_VARIANT -#define DEFAULT_XKB_VARIANT NULL -#endif - -#ifndef DEFAULT_XKB_OPTIONS -#define DEFAULT_XKB_OPTIONS NULL -#endif - /** * Create a new context. */ @@ -328,47 +279,6 @@ xkb_context_new(enum xkb_context_flags flags) return ctx; } -xkb_atom_t -xkb_atom_lookup(struct xkb_context *ctx, const char *string) -{ - return atom_lookup(ctx->atom_table, string); -} - -xkb_atom_t -xkb_atom_intern(struct xkb_context *ctx, const char *string) -{ - return atom_intern(ctx->atom_table, string, false); -} - -xkb_atom_t -xkb_atom_steal(struct xkb_context *ctx, char *string) -{ - return atom_intern(ctx->atom_table, string, true); -} - -char * -xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom) -{ - return atom_strdup(ctx->atom_table, atom); -} - -const char * -xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom) -{ - return atom_text(ctx->atom_table, atom); -} - -void -xkb_log(struct xkb_context *ctx, enum xkb_log_level level, - const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - ctx->log_fn(ctx, level, fmt, args); - va_end(args); -} - XKB_EXPORT void xkb_context_set_log_fn(struct xkb_context *ctx, void (*log_fn)(struct xkb_context *ctx, @@ -415,78 +325,3 @@ xkb_context_set_user_data(struct xkb_context *ctx, void *user_data) { ctx->user_data = user_data; } - -char * -xkb_context_get_buffer(struct xkb_context *ctx, size_t size) -{ - char *rtrn; - - if (size >= sizeof(ctx->text_buffer)) - return NULL; - - if (sizeof(ctx->text_buffer) - ctx->text_next <= size) - ctx->text_next = 0; - - rtrn = &ctx->text_buffer[ctx->text_next]; - ctx->text_next += size; - - return rtrn; -} - -const char * -xkb_context_get_default_rules(struct xkb_context *ctx) -{ - const char *env = NULL; - - if (ctx->use_environment_names) - env = getenv("XKB_DEFAULT_RULES"); - - return env ? env : DEFAULT_XKB_RULES; -} - -const char * -xkb_context_get_default_model(struct xkb_context *ctx) -{ - const char *env = NULL; - - if (ctx->use_environment_names) - env = getenv("XKB_DEFAULT_MODEL"); - - return env ? env : DEFAULT_XKB_MODEL; -} - -const char * -xkb_context_get_default_layout(struct xkb_context *ctx) -{ - const char *env = NULL; - - if (ctx->use_environment_names) - env = getenv("XKB_DEFAULT_LAYOUT"); - - return env ? env : DEFAULT_XKB_LAYOUT; -} - -const char * -xkb_context_get_default_variant(struct xkb_context *ctx) -{ - const char *env = NULL; - const char *layout = getenv("XKB_DEFAULT_VARIANT"); - - /* We don't want to inherit the variant if they haven't also set a - * layout, since they're so closely paired. */ - if (layout && ctx->use_environment_names) - env = getenv("XKB_DEFAULT_VARIANT"); - - return env ? env : DEFAULT_XKB_VARIANT; -} - -const char * -xkb_context_get_default_options(struct xkb_context *ctx) -{ - const char *env = NULL; - - if (ctx->use_environment_names) - env = getenv("XKB_DEFAULT_OPTIONS"); - - return env ? env : DEFAULT_XKB_OPTIONS; -} diff --git a/src/3rdparty/xkbcommon/src/context.h b/src/3rdparty/xkbcommon/src/context.h index 7c061a086f..486f4085a6 100644 --- a/src/3rdparty/xkbcommon/src/context.h +++ b/src/3rdparty/xkbcommon/src/context.h @@ -28,6 +28,30 @@ #include "atom.h" +struct xkb_context { + int refcnt; + + ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx, + enum xkb_log_level level, + const char *fmt, va_list args); + enum xkb_log_level log_level; + int log_verbosity; + void *user_data; + + struct xkb_rule_names names_dflt; + + darray(char *) includes; + darray(char *) failed_includes; + + struct atom_table *atom_table; + + /* Buffer for the *Text() functions. */ + char text_buffer[2048]; + size_t text_next; + + unsigned int use_environment_names : 1; +}; + unsigned int xkb_context_num_failed_include_paths(struct xkb_context *ctx); @@ -43,40 +67,30 @@ xkb_atom_t xkb_atom_lookup(struct xkb_context *ctx, const char *string); xkb_atom_t -xkb_atom_intern(struct xkb_context *ctx, const char *string); +xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len); + +#define xkb_atom_intern_literal(ctx, literal) \ + xkb_atom_intern((ctx), (literal), sizeof(literal) - 1) /** - * If @string is dynamically allocated, free'd immediately after - * being interned, and not used afterwards, use this function + * If @string is dynamically allocated, NUL-terminated, free'd immediately + * after being interned, and not used afterwards, use this function * instead of xkb_atom_intern to avoid some unnecessary allocations. * The caller should not use or free the passed in string afterwards. */ xkb_atom_t xkb_atom_steal(struct xkb_context *ctx, char *string); -char * -xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom); - const char * xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom); char * xkb_context_get_buffer(struct xkb_context *ctx, size_t size); -ATTR_PRINTF(3, 4) void -xkb_log(struct xkb_context *ctx, enum xkb_log_level level, +ATTR_PRINTF(4, 5) void +xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity, const char *fmt, ...); -#define xkb_log_cond_level(ctx, level, ...) do { \ - if (xkb_context_get_log_level(ctx) >= (level)) \ - xkb_log((ctx), (level), __VA_ARGS__); \ -} while (0) - -#define xkb_log_cond_verbosity(ctx, level, vrb, ...) do { \ - if (xkb_context_get_log_verbosity(ctx) >= (vrb)) \ - xkb_log_cond_level((ctx), (level), __VA_ARGS__); \ -} while (0) - const char * xkb_context_get_default_rules(struct xkb_context *ctx); @@ -99,17 +113,17 @@ xkb_context_get_default_options(struct xkb_context *ctx); * result in an error, though. */ #define log_dbg(ctx, ...) \ - xkb_log_cond_level((ctx), XKB_LOG_LEVEL_DEBUG, __VA_ARGS__) + xkb_log((ctx), XKB_LOG_LEVEL_DEBUG, 0, __VA_ARGS__) #define log_info(ctx, ...) \ - xkb_log_cond_level((ctx), XKB_LOG_LEVEL_INFO, __VA_ARGS__) + xkb_log((ctx), XKB_LOG_LEVEL_INFO, 0, __VA_ARGS__) #define log_warn(ctx, ...) \ - xkb_log_cond_level((ctx), XKB_LOG_LEVEL_WARNING, __VA_ARGS__) + xkb_log((ctx), XKB_LOG_LEVEL_WARNING, 0, __VA_ARGS__) #define log_err(ctx, ...) \ - xkb_log_cond_level((ctx), XKB_LOG_LEVEL_ERROR, __VA_ARGS__) + xkb_log((ctx), XKB_LOG_LEVEL_ERROR, 0, __VA_ARGS__) #define log_wsgo(ctx, ...) \ - xkb_log_cond_level((ctx), XKB_LOG_LEVEL_CRITICAL, __VA_ARGS__) + xkb_log((ctx), XKB_LOG_LEVEL_CRITICAL, 0, __VA_ARGS__) #define log_vrb(ctx, vrb, ...) \ - xkb_log_cond_verbosity((ctx), XKB_LOG_LEVEL_WARNING, (vrb), __VA_ARGS__) + xkb_log((ctx), XKB_LOG_LEVEL_WARNING, (vrb), __VA_ARGS__) /* * Variants which are prefixed by the name of the function they're diff --git a/src/3rdparty/xkbcommon/src/keymap-priv.c b/src/3rdparty/xkbcommon/src/keymap-priv.c new file mode 100644 index 0000000000..9f42040828 --- /dev/null +++ b/src/3rdparty/xkbcommon/src/keymap-priv.c @@ -0,0 +1,121 @@ +/** + * Copyright © 2012 Intel Corporation + * Copyright © 2012 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone + */ + +#include "keymap.h" + +static void +update_builtin_keymap_fields(struct xkb_keymap *keymap) +{ + struct xkb_context *ctx = keymap->ctx; + + /* + * Add predefined (AKA real, core, X11) modifiers. + * The order is important! + */ + darray_appends_t(keymap->mods, struct xkb_mod, + { .name = xkb_atom_intern_literal(ctx, "Shift"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Lock"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Control"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Mod1"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Mod2"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Mod3"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Mod4"), .type = MOD_REAL }, + { .name = xkb_atom_intern_literal(ctx, "Mod5"), .type = MOD_REAL }); +} + +struct xkb_keymap * +xkb_keymap_new(struct xkb_context *ctx, + enum xkb_keymap_format format, + enum xkb_keymap_compile_flags flags) +{ + struct xkb_keymap *keymap; + + keymap = calloc(1, sizeof(*keymap)); + if (!keymap) + return NULL; + + keymap->refcnt = 1; + keymap->ctx = xkb_context_ref(ctx); + + keymap->format = format; + keymap->flags = flags; + + update_builtin_keymap_fields(keymap); + + return keymap; +} + +struct xkb_key * +XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases) +{ + struct xkb_key *key; + + xkb_foreach_key(key, keymap) + if (key->name == name) + return key; + + if (use_aliases) { + xkb_atom_t new_name = XkbResolveKeyAlias(keymap, name); + if (new_name != XKB_ATOM_NONE) + return XkbKeyByName(keymap, new_name, false); + } + + return NULL; +} + +xkb_atom_t +XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name) +{ + for (unsigned i = 0; i < keymap->num_key_aliases; i++) + if (keymap->key_aliases[i].alias == name) + return keymap->key_aliases[i].real; + + return XKB_ATOM_NONE; +} + +void +XkbEscapeMapName(char *name) +{ + /* + * All latin-1 alphanumerics, plus parens, slash, minus, underscore and + * wildcards. + */ + static const unsigned char legal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff + }; + + if (!name) + return; + + while (*name) { + if (!(legal[*name / 8] & (1 << (*name % 8)))) + *name = '_'; + name++; + } +} diff --git a/src/3rdparty/xkbcommon/src/keymap.h b/src/3rdparty/xkbcommon/src/keymap.h index c6b884d6bc..5f514ec779 100644 --- a/src/3rdparty/xkbcommon/src/keymap.h +++ b/src/3rdparty/xkbcommon/src/keymap.h @@ -133,7 +133,6 @@ enum xkb_action_type { ACTION_TYPE_SWITCH_VT, ACTION_TYPE_CTRL_SET, ACTION_TYPE_CTRL_LOCK, - ACTION_TYPE_KEY_REDIRECT, ACTION_TYPE_PRIVATE, _ACTION_TYPE_NUM_ENTRIES }; @@ -213,16 +212,6 @@ struct xkb_switch_screen_action { int8_t screen; }; -struct xkb_redirect_key_action { - enum xkb_action_type type; - enum xkb_action_flags flags; - xkb_keycode_t new_kc; - uint8_t mods_mask; - uint8_t mods; - uint16_t vmods_mask; - uint16_t vmods; -}; - struct xkb_pointer_action { enum xkb_action_type type; enum xkb_action_flags flags; @@ -250,7 +239,6 @@ union xkb_action { struct xkb_controls_action ctrls; struct xkb_pointer_default_action dflt; struct xkb_switch_screen_action screen; - struct xkb_redirect_key_action redirect; /* XXX wholly unnecessary? */ struct xkb_pointer_action ptr; struct xkb_pointer_button_action btn; struct xkb_private_action priv; @@ -313,8 +301,8 @@ struct xkb_controls { /* Such an awkward name. Oh well. */ enum xkb_range_exceed_type { + RANGE_WRAP = 0, RANGE_SATURATE, - RANGE_WRAP, RANGE_REDIRECT, }; @@ -386,7 +374,8 @@ struct xkb_keymap { struct xkb_key_type *types; unsigned int num_types; - darray(struct xkb_sym_interpret) sym_interprets; + unsigned int num_sym_interprets; + struct xkb_sym_interpret *sym_interprets; darray(struct xkb_mod) mods; @@ -423,12 +412,20 @@ XkbKeyGroupWidth(const struct xkb_key *key, xkb_layout_index_t layout) return key->groups[layout].type->num_levels; } +struct xkb_keymap * +xkb_keymap_new(struct xkb_context *ctx, + enum xkb_keymap_format format, + enum xkb_keymap_compile_flags flags); + struct xkb_key * XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases); xkb_atom_t XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name); +void +XkbEscapeMapName(char *name); + xkb_layout_index_t wrap_group_into_range(int32_t group, xkb_layout_index_t num_groups, @@ -439,9 +436,7 @@ struct xkb_keymap_format_ops { bool (*keymap_new_from_names)(struct xkb_keymap *keymap, const struct xkb_rule_names *names); bool (*keymap_new_from_string)(struct xkb_keymap *keymap, - const char *string); - bool (*keymap_new_from_buffer)(struct xkb_keymap *keymap, - const char *buffer, size_t length); + const char *string, size_t length); bool (*keymap_new_from_file)(struct xkb_keymap *keymap, FILE *file); char *(*keymap_get_as_string)(struct xkb_keymap *keymap); }; diff --git a/src/3rdparty/xkbcommon/src/keysym-utf.c b/src/3rdparty/xkbcommon/src/keysym-utf.c index 5484a8311d..129da15cf8 100644 --- a/src/3rdparty/xkbcommon/src/keysym-utf.c +++ b/src/3rdparty/xkbcommon/src/keysym-utf.c @@ -838,20 +838,19 @@ static const struct codepair keysymtab[] = { static uint32_t bin_search(const struct codepair *table, size_t length, xkb_keysym_t keysym) { - int min = 0; - int max = length; - int mid; + int first = 0; + int last = length; if (keysym < table[0].keysym || keysym > table[length].keysym) return 0; /* binary search in table */ - while (max >= min) { - mid = (min + max) / 2; + while (last >= first) { + int mid = (first + last) / 2; if (table[mid].keysym < keysym) - min = mid + 1; + first = mid + 1; else if (table[mid].keysym > keysym) - max = mid - 1; + last = mid - 1; else /* found it */ return table[mid].ucs; } diff --git a/src/3rdparty/xkbcommon/src/keysym.c b/src/3rdparty/xkbcommon/src/keysym.c index 1e92a4ac9f..f52d751973 100644 --- a/src/3rdparty/xkbcommon/src/keysym.c +++ b/src/3rdparty/xkbcommon/src/keysym.c @@ -53,24 +53,31 @@ #include "keysym.h" #include "ks_tables.h" +static inline const char * +get_name(const struct name_keysym *entry) +{ + return keysym_names + entry->offset; +} + static int compare_by_keysym(const void *a, const void *b) { - const struct name_keysym *key = a, *entry = b; - return key->keysym - (int32_t)entry->keysym; + const xkb_keysym_t *key = a; + const struct name_keysym *entry = b; + return *key - (int32_t) entry->keysym; } static int compare_by_name(const void *a, const void *b) { - const struct name_keysym *key = a, *entry = b; - return strcasecmp(key->name, entry->name); + const char *key = a; + const struct name_keysym *entry = b; + return strcasecmp(key, get_name(entry)); } XKB_EXPORT int xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size) { - const struct name_keysym search = { .name = NULL, .keysym = ks }; const struct name_keysym *entry; if ((ks & ((unsigned long) ~0x1fffffff)) != 0) { @@ -78,12 +85,12 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size) return -1; } - entry = bsearch(&search, keysym_to_name, + entry = bsearch(&ks, keysym_to_name, ARRAY_SIZE(keysym_to_name), sizeof(*keysym_to_name), compare_by_keysym); if (entry) - return snprintf(buffer, size, "%s", entry->name); + return snprintf(buffer, size, "%s", get_name(entry)); /* Unnamed Unicode codepoint. */ if (ks >= 0x01000100 && ks <= 0x0110ffff) { @@ -119,25 +126,25 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase) if (!entry) return NULL; - if (!icase && strcmp(entry->name, name) == 0) + if (!icase && strcmp(get_name(entry), name) == 0) return entry; if (icase && xkb_keysym_is_lower(entry->keysym)) return entry; for (iter = entry - 1; iter >= name_to_keysym; --iter) { - if (!icase && strcmp(iter->name, name) == 0) + if (!icase && strcmp(get_name(iter), name) == 0) return iter; - if (strcasecmp(iter->name, entry->name) != 0) + if (strcasecmp(get_name(iter), get_name(entry)) != 0) break; if (icase && xkb_keysym_is_lower(iter->keysym)) return iter; } last = name_to_keysym + len; - for (iter = entry + 1; iter < last; --iter) { - if (!icase && strcmp(iter->name, name) == 0) + for (iter = entry + 1; iter < last; ++iter) { + if (!icase && strcmp(get_name(iter), name) == 0) return iter; - if (strcasecmp(iter->name, entry->name) != 0) + if (strcasecmp(get_name(iter), get_name(entry)) != 0) break; if (icase && xkb_keysym_is_lower(iter->keysym)) return iter; @@ -151,7 +158,6 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase) XKB_EXPORT xkb_keysym_t xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags) { - const struct name_keysym search = { .name = s, .keysym = 0 }; const struct name_keysym *entry; char *tmp; xkb_keysym_t val; @@ -160,7 +166,7 @@ xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags) if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE) return XKB_KEY_NoSymbol; - entry = bsearch(&search, name_to_keysym, + entry = bsearch(s, name_to_keysym, ARRAY_SIZE(name_to_keysym), sizeof(*name_to_keysym), compare_by_name); @@ -242,6 +248,26 @@ xkb_keysym_is_upper(xkb_keysym_t ks) return (ks == upper ? true : false); } +xkb_keysym_t +xkb_keysym_to_lower(xkb_keysym_t ks) +{ + xkb_keysym_t lower, upper; + + XConvertCase(ks, &lower, &upper); + + return lower; +} + +xkb_keysym_t +xkb_keysym_to_upper(xkb_keysym_t ks) +{ + xkb_keysym_t lower, upper; + + XConvertCase(ks, &lower, &upper); + + return upper; +} + /* * The following is copied verbatim from libX11:src/KeyBind.c, commit * d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes: diff --git a/src/3rdparty/xkbcommon/src/keysym.h b/src/3rdparty/xkbcommon/src/keysym.h index 6f2280bfd4..e9374dc492 100644 --- a/src/3rdparty/xkbcommon/src/keysym.h +++ b/src/3rdparty/xkbcommon/src/keysym.h @@ -59,4 +59,10 @@ xkb_keysym_is_upper(xkb_keysym_t keysym); bool xkb_keysym_is_keypad(xkb_keysym_t keysym); +xkb_keysym_t +xkb_keysym_to_upper(xkb_keysym_t ks); + +xkb_keysym_t +xkb_keysym_to_lower(xkb_keysym_t ks); + #endif diff --git a/src/3rdparty/xkbcommon/src/ks_tables.h b/src/3rdparty/xkbcommon/src/ks_tables.h index a7e2b4705f..1010b694e4 100644 --- a/src/3rdparty/xkbcommon/src/ks_tables.h +++ b/src/3rdparty/xkbcommon/src/ks_tables.h @@ -1,4681 +1,7104 @@ -/* This file is autogenerated from Makefile.am; please do not commit directly. */ + +/** + * This file comes from libxkbcommon and was generated by makekeys.py + * You can always fetch the latest version from: + * https://raw.github.com/xkbcommon/libxkbcommon/master/src/ks_tables.h + */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverlength-strings" +static const char *keysym_names = + "0\0" + "1\0" + "2\0" + "3\0" + "3270_AltCursor\0" + "3270_Attn\0" + "3270_BackTab\0" + "3270_ChangeScreen\0" + "3270_Copy\0" + "3270_CursorBlink\0" + "3270_CursorSelect\0" + "3270_DeleteWord\0" + "3270_Duplicate\0" + "3270_Enter\0" + "3270_EraseEOF\0" + "3270_EraseInput\0" + "3270_ExSelect\0" + "3270_FieldMark\0" + "3270_Ident\0" + "3270_Jump\0" + "3270_KeyClick\0" + "3270_Left2\0" + "3270_PA1\0" + "3270_PA2\0" + "3270_PA3\0" + "3270_Play\0" + "3270_PrintScreen\0" + "3270_Quit\0" + "3270_Record\0" + "3270_Reset\0" + "3270_Right2\0" + "3270_Rule\0" + "3270_Setup\0" + "3270_Test\0" + "4\0" + "5\0" + "6\0" + "7\0" + "8\0" + "9\0" + "A\0" + "a\0" + "Aacute\0" + "aacute\0" + "Abelowdot\0" + "abelowdot\0" + "abovedot\0" + "Abreve\0" + "abreve\0" + "Abreveacute\0" + "abreveacute\0" + "Abrevebelowdot\0" + "abrevebelowdot\0" + "Abrevegrave\0" + "abrevegrave\0" + "Abrevehook\0" + "abrevehook\0" + "Abrevetilde\0" + "abrevetilde\0" + "AccessX_Enable\0" + "AccessX_Feedback_Enable\0" + "Acircumflex\0" + "acircumflex\0" + "Acircumflexacute\0" + "acircumflexacute\0" + "Acircumflexbelowdot\0" + "acircumflexbelowdot\0" + "Acircumflexgrave\0" + "acircumflexgrave\0" + "Acircumflexhook\0" + "acircumflexhook\0" + "Acircumflextilde\0" + "acircumflextilde\0" + "acute\0" + "Adiaeresis\0" + "adiaeresis\0" + "AE\0" + "ae\0" + "Agrave\0" + "agrave\0" + "Ahook\0" + "ahook\0" + "Alt_L\0" + "Alt_R\0" + "Amacron\0" + "amacron\0" + "ampersand\0" + "Aogonek\0" + "aogonek\0" + "apostrophe\0" + "approxeq\0" + "approximate\0" + "Arabic_0\0" + "Arabic_1\0" + "Arabic_2\0" + "Arabic_3\0" + "Arabic_4\0" + "Arabic_5\0" + "Arabic_6\0" + "Arabic_7\0" + "Arabic_8\0" + "Arabic_9\0" + "Arabic_ain\0" + "Arabic_alef\0" + "Arabic_alefmaksura\0" + "Arabic_beh\0" + "Arabic_comma\0" + "Arabic_dad\0" + "Arabic_dal\0" + "Arabic_damma\0" + "Arabic_dammatan\0" + "Arabic_ddal\0" + "Arabic_farsi_yeh\0" + "Arabic_fatha\0" + "Arabic_fathatan\0" + "Arabic_feh\0" + "Arabic_fullstop\0" + "Arabic_gaf\0" + "Arabic_ghain\0" + "Arabic_ha\0" + "Arabic_hah\0" + "Arabic_hamza\0" + "Arabic_hamza_above\0" + "Arabic_hamza_below\0" + "Arabic_hamzaonalef\0" + "Arabic_hamzaonwaw\0" + "Arabic_hamzaonyeh\0" + "Arabic_hamzaunderalef\0" + "Arabic_heh\0" + "Arabic_heh_doachashmee\0" + "Arabic_heh_goal\0" + "Arabic_jeem\0" + "Arabic_jeh\0" + "Arabic_kaf\0" + "Arabic_kasra\0" + "Arabic_kasratan\0" + "Arabic_keheh\0" + "Arabic_khah\0" + "Arabic_lam\0" + "Arabic_madda_above\0" + "Arabic_maddaonalef\0" + "Arabic_meem\0" + "Arabic_noon\0" + "Arabic_noon_ghunna\0" + "Arabic_peh\0" + "Arabic_percent\0" + "Arabic_qaf\0" + "Arabic_question_mark\0" + "Arabic_ra\0" + "Arabic_rreh\0" + "Arabic_sad\0" + "Arabic_seen\0" + "Arabic_semicolon\0" + "Arabic_shadda\0" + "Arabic_sheen\0" + "Arabic_sukun\0" + "Arabic_superscript_alef\0" + "Arabic_switch\0" + "Arabic_tah\0" + "Arabic_tatweel\0" + "Arabic_tcheh\0" + "Arabic_teh\0" + "Arabic_tehmarbuta\0" + "Arabic_thal\0" + "Arabic_theh\0" + "Arabic_tteh\0" + "Arabic_veh\0" + "Arabic_waw\0" + "Arabic_yeh\0" + "Arabic_yeh_baree\0" + "Arabic_zah\0" + "Arabic_zain\0" + "Aring\0" + "aring\0" + "Armenian_accent\0" + "Armenian_amanak\0" + "Armenian_apostrophe\0" + "Armenian_AT\0" + "Armenian_at\0" + "Armenian_AYB\0" + "Armenian_ayb\0" + "Armenian_BEN\0" + "Armenian_ben\0" + "Armenian_but\0" + "Armenian_CHA\0" + "Armenian_cha\0" + "Armenian_DA\0" + "Armenian_da\0" + "Armenian_DZA\0" + "Armenian_dza\0" + "Armenian_E\0" + "Armenian_e\0" + "Armenian_exclam\0" + "Armenian_FE\0" + "Armenian_fe\0" + "Armenian_full_stop\0" + "Armenian_GHAT\0" + "Armenian_ghat\0" + "Armenian_GIM\0" + "Armenian_gim\0" + "Armenian_HI\0" + "Armenian_hi\0" + "Armenian_HO\0" + "Armenian_ho\0" + "Armenian_hyphen\0" + "Armenian_INI\0" + "Armenian_ini\0" + "Armenian_JE\0" + "Armenian_je\0" + "Armenian_KE\0" + "Armenian_ke\0" + "Armenian_KEN\0" + "Armenian_ken\0" + "Armenian_KHE\0" + "Armenian_khe\0" + "Armenian_ligature_ew\0" + "Armenian_LYUN\0" + "Armenian_lyun\0" + "Armenian_MEN\0" + "Armenian_men\0" + "Armenian_NU\0" + "Armenian_nu\0" + "Armenian_O\0" + "Armenian_o\0" + "Armenian_paruyk\0" + "Armenian_PE\0" + "Armenian_pe\0" + "Armenian_PYUR\0" + "Armenian_pyur\0" + "Armenian_question\0" + "Armenian_RA\0" + "Armenian_ra\0" + "Armenian_RE\0" + "Armenian_re\0" + "Armenian_SE\0" + "Armenian_se\0" + "Armenian_separation_mark\0" + "Armenian_SHA\0" + "Armenian_sha\0" + "Armenian_shesht\0" + "Armenian_TCHE\0" + "Armenian_tche\0" + "Armenian_TO\0" + "Armenian_to\0" + "Armenian_TSA\0" + "Armenian_tsa\0" + "Armenian_TSO\0" + "Armenian_tso\0" + "Armenian_TYUN\0" + "Armenian_tyun\0" + "Armenian_verjaket\0" + "Armenian_VEV\0" + "Armenian_vev\0" + "Armenian_VO\0" + "Armenian_vo\0" + "Armenian_VYUN\0" + "Armenian_vyun\0" + "Armenian_YECH\0" + "Armenian_yech\0" + "Armenian_yentamna\0" + "Armenian_ZA\0" + "Armenian_za\0" + "Armenian_ZHE\0" + "Armenian_zhe\0" + "asciicircum\0" + "asciitilde\0" + "asterisk\0" + "at\0" + "Atilde\0" + "atilde\0" + "AudibleBell_Enable\0" + "B\0" + "b\0" + "Babovedot\0" + "babovedot\0" + "backslash\0" + "BackSpace\0" + "BackTab\0" + "ballotcross\0" + "bar\0" + "because\0" + "Begin\0" + "blank\0" + "block\0" + "botintegral\0" + "botleftparens\0" + "botleftsqbracket\0" + "botleftsummation\0" + "botrightparens\0" + "botrightsqbracket\0" + "botrightsummation\0" + "bott\0" + "botvertsummationconnector\0" + "BounceKeys_Enable\0" + "braceleft\0" + "braceright\0" + "bracketleft\0" + "bracketright\0" + "braille_blank\0" + "braille_dot_1\0" + "braille_dot_10\0" + "braille_dot_2\0" + "braille_dot_3\0" + "braille_dot_4\0" + "braille_dot_5\0" + "braille_dot_6\0" + "braille_dot_7\0" + "braille_dot_8\0" + "braille_dot_9\0" + "braille_dots_1\0" + "braille_dots_12\0" + "braille_dots_123\0" + "braille_dots_1234\0" + "braille_dots_12345\0" + "braille_dots_123456\0" + "braille_dots_1234567\0" + "braille_dots_12345678\0" + "braille_dots_1234568\0" + "braille_dots_123457\0" + "braille_dots_1234578\0" + "braille_dots_123458\0" + "braille_dots_12346\0" + "braille_dots_123467\0" + "braille_dots_1234678\0" + "braille_dots_123468\0" + "braille_dots_12347\0" + "braille_dots_123478\0" + "braille_dots_12348\0" + "braille_dots_1235\0" + "braille_dots_12356\0" + "braille_dots_123567\0" + "braille_dots_1235678\0" + "braille_dots_123568\0" + "braille_dots_12357\0" + "braille_dots_123578\0" + "braille_dots_12358\0" + "braille_dots_1236\0" + "braille_dots_12367\0" + "braille_dots_123678\0" + "braille_dots_12368\0" + "braille_dots_1237\0" + "braille_dots_12378\0" + "braille_dots_1238\0" + "braille_dots_124\0" + "braille_dots_1245\0" + "braille_dots_12456\0" + "braille_dots_124567\0" + "braille_dots_1245678\0" + "braille_dots_124568\0" + "braille_dots_12457\0" + "braille_dots_124578\0" + "braille_dots_12458\0" + "braille_dots_1246\0" + "braille_dots_12467\0" + "braille_dots_124678\0" + "braille_dots_12468\0" + "braille_dots_1247\0" + "braille_dots_12478\0" + "braille_dots_1248\0" + "braille_dots_125\0" + "braille_dots_1256\0" + "braille_dots_12567\0" + "braille_dots_125678\0" + "braille_dots_12568\0" + "braille_dots_1257\0" + "braille_dots_12578\0" + "braille_dots_1258\0" + "braille_dots_126\0" + "braille_dots_1267\0" + "braille_dots_12678\0" + "braille_dots_1268\0" + "braille_dots_127\0" + "braille_dots_1278\0" + "braille_dots_128\0" + "braille_dots_13\0" + "braille_dots_134\0" + "braille_dots_1345\0" + "braille_dots_13456\0" + "braille_dots_134567\0" + "braille_dots_1345678\0" + "braille_dots_134568\0" + "braille_dots_13457\0" + "braille_dots_134578\0" + "braille_dots_13458\0" + "braille_dots_1346\0" + "braille_dots_13467\0" + "braille_dots_134678\0" + "braille_dots_13468\0" + "braille_dots_1347\0" + "braille_dots_13478\0" + "braille_dots_1348\0" + "braille_dots_135\0" + "braille_dots_1356\0" + "braille_dots_13567\0" + "braille_dots_135678\0" + "braille_dots_13568\0" + "braille_dots_1357\0" + "braille_dots_13578\0" + "braille_dots_1358\0" + "braille_dots_136\0" + "braille_dots_1367\0" + "braille_dots_13678\0" + "braille_dots_1368\0" + "braille_dots_137\0" + "braille_dots_1378\0" + "braille_dots_138\0" + "braille_dots_14\0" + "braille_dots_145\0" + "braille_dots_1456\0" + "braille_dots_14567\0" + "braille_dots_145678\0" + "braille_dots_14568\0" + "braille_dots_1457\0" + "braille_dots_14578\0" + "braille_dots_1458\0" + "braille_dots_146\0" + "braille_dots_1467\0" + "braille_dots_14678\0" + "braille_dots_1468\0" + "braille_dots_147\0" + "braille_dots_1478\0" + "braille_dots_148\0" + "braille_dots_15\0" + "braille_dots_156\0" + "braille_dots_1567\0" + "braille_dots_15678\0" + "braille_dots_1568\0" + "braille_dots_157\0" + "braille_dots_1578\0" + "braille_dots_158\0" + "braille_dots_16\0" + "braille_dots_167\0" + "braille_dots_1678\0" + "braille_dots_168\0" + "braille_dots_17\0" + "braille_dots_178\0" + "braille_dots_18\0" + "braille_dots_2\0" + "braille_dots_23\0" + "braille_dots_234\0" + "braille_dots_2345\0" + "braille_dots_23456\0" + "braille_dots_234567\0" + "braille_dots_2345678\0" + "braille_dots_234568\0" + "braille_dots_23457\0" + "braille_dots_234578\0" + "braille_dots_23458\0" + "braille_dots_2346\0" + "braille_dots_23467\0" + "braille_dots_234678\0" + "braille_dots_23468\0" + "braille_dots_2347\0" + "braille_dots_23478\0" + "braille_dots_2348\0" + "braille_dots_235\0" + "braille_dots_2356\0" + "braille_dots_23567\0" + "braille_dots_235678\0" + "braille_dots_23568\0" + "braille_dots_2357\0" + "braille_dots_23578\0" + "braille_dots_2358\0" + "braille_dots_236\0" + "braille_dots_2367\0" + "braille_dots_23678\0" + "braille_dots_2368\0" + "braille_dots_237\0" + "braille_dots_2378\0" + "braille_dots_238\0" + "braille_dots_24\0" + "braille_dots_245\0" + "braille_dots_2456\0" + "braille_dots_24567\0" + "braille_dots_245678\0" + "braille_dots_24568\0" + "braille_dots_2457\0" + "braille_dots_24578\0" + "braille_dots_2458\0" + "braille_dots_246\0" + "braille_dots_2467\0" + "braille_dots_24678\0" + "braille_dots_2468\0" + "braille_dots_247\0" + "braille_dots_2478\0" + "braille_dots_248\0" + "braille_dots_25\0" + "braille_dots_256\0" + "braille_dots_2567\0" + "braille_dots_25678\0" + "braille_dots_2568\0" + "braille_dots_257\0" + "braille_dots_2578\0" + "braille_dots_258\0" + "braille_dots_26\0" + "braille_dots_267\0" + "braille_dots_2678\0" + "braille_dots_268\0" + "braille_dots_27\0" + "braille_dots_278\0" + "braille_dots_28\0" + "braille_dots_3\0" + "braille_dots_34\0" + "braille_dots_345\0" + "braille_dots_3456\0" + "braille_dots_34567\0" + "braille_dots_345678\0" + "braille_dots_34568\0" + "braille_dots_3457\0" + "braille_dots_34578\0" + "braille_dots_3458\0" + "braille_dots_346\0" + "braille_dots_3467\0" + "braille_dots_34678\0" + "braille_dots_3468\0" + "braille_dots_347\0" + "braille_dots_3478\0" + "braille_dots_348\0" + "braille_dots_35\0" + "braille_dots_356\0" + "braille_dots_3567\0" + "braille_dots_35678\0" + "braille_dots_3568\0" + "braille_dots_357\0" + "braille_dots_3578\0" + "braille_dots_358\0" + "braille_dots_36\0" + "braille_dots_367\0" + "braille_dots_3678\0" + "braille_dots_368\0" + "braille_dots_37\0" + "braille_dots_378\0" + "braille_dots_38\0" + "braille_dots_4\0" + "braille_dots_45\0" + "braille_dots_456\0" + "braille_dots_4567\0" + "braille_dots_45678\0" + "braille_dots_4568\0" + "braille_dots_457\0" + "braille_dots_4578\0" + "braille_dots_458\0" + "braille_dots_46\0" + "braille_dots_467\0" + "braille_dots_4678\0" + "braille_dots_468\0" + "braille_dots_47\0" + "braille_dots_478\0" + "braille_dots_48\0" + "braille_dots_5\0" + "braille_dots_56\0" + "braille_dots_567\0" + "braille_dots_5678\0" + "braille_dots_568\0" + "braille_dots_57\0" + "braille_dots_578\0" + "braille_dots_58\0" + "braille_dots_6\0" + "braille_dots_67\0" + "braille_dots_678\0" + "braille_dots_68\0" + "braille_dots_7\0" + "braille_dots_78\0" + "braille_dots_8\0" + "Break\0" + "breve\0" + "brokenbar\0" + "Byelorussian_shortu\0" + "Byelorussian_SHORTU\0" + "C\0" + "c\0" + "c_h\0" + "C_h\0" + "C_H\0" + "Cabovedot\0" + "cabovedot\0" + "Cacute\0" + "cacute\0" + "Cancel\0" + "Caps_Lock\0" + "careof\0" + "caret\0" + "caron\0" + "Ccaron\0" + "ccaron\0" + "Ccedilla\0" + "ccedilla\0" + "Ccircumflex\0" + "ccircumflex\0" + "cedilla\0" + "cent\0" + "ch\0" + "Ch\0" + "CH\0" + "checkerboard\0" + "checkmark\0" + "circle\0" + "Clear\0" + "ClearLine\0" + "club\0" + "Codeinput\0" + "colon\0" + "ColonSign\0" + "comma\0" + "containsas\0" + "Control_L\0" + "Control_R\0" + "copyright\0" + "cr\0" + "crossinglines\0" + "CruzeiroSign\0" + "cuberoot\0" + "currency\0" + "cursor\0" + "Cyrillic_a\0" + "Cyrillic_A\0" + "Cyrillic_be\0" + "Cyrillic_BE\0" + "Cyrillic_che\0" + "Cyrillic_CHE\0" + "Cyrillic_CHE_descender\0" + "Cyrillic_che_descender\0" + "Cyrillic_CHE_vertstroke\0" + "Cyrillic_che_vertstroke\0" + "Cyrillic_de\0" + "Cyrillic_DE\0" + "Cyrillic_dzhe\0" + "Cyrillic_DZHE\0" + "Cyrillic_e\0" + "Cyrillic_E\0" + "Cyrillic_ef\0" + "Cyrillic_EF\0" + "Cyrillic_el\0" + "Cyrillic_EL\0" + "Cyrillic_em\0" + "Cyrillic_EM\0" + "Cyrillic_en\0" + "Cyrillic_EN\0" + "Cyrillic_EN_descender\0" + "Cyrillic_en_descender\0" + "Cyrillic_er\0" + "Cyrillic_ER\0" + "Cyrillic_es\0" + "Cyrillic_ES\0" + "Cyrillic_ghe\0" + "Cyrillic_GHE\0" + "Cyrillic_GHE_bar\0" + "Cyrillic_ghe_bar\0" + "Cyrillic_ha\0" + "Cyrillic_HA\0" + "Cyrillic_HA_descender\0" + "Cyrillic_ha_descender\0" + "Cyrillic_hardsign\0" + "Cyrillic_HARDSIGN\0" + "Cyrillic_i\0" + "Cyrillic_I\0" + "Cyrillic_I_macron\0" + "Cyrillic_i_macron\0" + "Cyrillic_ie\0" + "Cyrillic_IE\0" + "Cyrillic_io\0" + "Cyrillic_IO\0" + "Cyrillic_je\0" + "Cyrillic_JE\0" + "Cyrillic_ka\0" + "Cyrillic_KA\0" + "Cyrillic_KA_descender\0" + "Cyrillic_ka_descender\0" + "Cyrillic_KA_vertstroke\0" + "Cyrillic_ka_vertstroke\0" + "Cyrillic_lje\0" + "Cyrillic_LJE\0" + "Cyrillic_nje\0" + "Cyrillic_NJE\0" + "Cyrillic_o\0" + "Cyrillic_O\0" + "Cyrillic_O_bar\0" + "Cyrillic_o_bar\0" + "Cyrillic_pe\0" + "Cyrillic_PE\0" + "Cyrillic_SCHWA\0" + "Cyrillic_schwa\0" + "Cyrillic_sha\0" + "Cyrillic_SHA\0" + "Cyrillic_shcha\0" + "Cyrillic_SHCHA\0" + "Cyrillic_SHHA\0" + "Cyrillic_shha\0" + "Cyrillic_shorti\0" + "Cyrillic_SHORTI\0" + "Cyrillic_softsign\0" + "Cyrillic_SOFTSIGN\0" + "Cyrillic_te\0" + "Cyrillic_TE\0" + "Cyrillic_tse\0" + "Cyrillic_TSE\0" + "Cyrillic_u\0" + "Cyrillic_U\0" + "Cyrillic_U_macron\0" + "Cyrillic_u_macron\0" + "Cyrillic_U_straight\0" + "Cyrillic_u_straight\0" + "Cyrillic_U_straight_bar\0" + "Cyrillic_u_straight_bar\0" + "Cyrillic_ve\0" + "Cyrillic_VE\0" + "Cyrillic_ya\0" + "Cyrillic_YA\0" + "Cyrillic_yeru\0" + "Cyrillic_YERU\0" + "Cyrillic_yu\0" + "Cyrillic_YU\0" + "Cyrillic_ze\0" + "Cyrillic_ZE\0" + "Cyrillic_zhe\0" + "Cyrillic_ZHE\0" + "Cyrillic_ZHE_descender\0" + "Cyrillic_zhe_descender\0" + "D\0" + "d\0" + "Dabovedot\0" + "dabovedot\0" + "Dacute_accent\0" + "dagger\0" + "Dcaron\0" + "dcaron\0" + "Dcedilla_accent\0" + "Dcircumflex_accent\0" + "Ddiaeresis\0" + "dead_a\0" + "dead_A\0" + "dead_abovecomma\0" + "dead_abovedot\0" + "dead_abovereversedcomma\0" + "dead_abovering\0" + "dead_aboveverticalline\0" + "dead_acute\0" + "dead_belowbreve\0" + "dead_belowcircumflex\0" + "dead_belowcomma\0" + "dead_belowdiaeresis\0" + "dead_belowdot\0" + "dead_belowmacron\0" + "dead_belowring\0" + "dead_belowtilde\0" + "dead_belowverticalline\0" + "dead_breve\0" + "dead_capital_schwa\0" + "dead_caron\0" + "dead_cedilla\0" + "dead_circumflex\0" + "dead_currency\0" + "dead_dasia\0" + "dead_diaeresis\0" + "dead_doubleacute\0" + "dead_doublegrave\0" + "dead_e\0" + "dead_E\0" + "dead_grave\0" + "dead_greek\0" + "dead_hook\0" + "dead_horn\0" + "dead_i\0" + "dead_I\0" + "dead_invertedbreve\0" + "dead_iota\0" + "dead_longsolidusoverlay\0" + "dead_lowline\0" + "dead_macron\0" + "dead_o\0" + "dead_O\0" + "dead_ogonek\0" + "dead_perispomeni\0" + "dead_psili\0" + "dead_semivoiced_sound\0" + "dead_small_schwa\0" + "dead_stroke\0" + "dead_tilde\0" + "dead_u\0" + "dead_U\0" + "dead_voiced_sound\0" + "decimalpoint\0" + "degree\0" + "Delete\0" + "DeleteChar\0" + "DeleteLine\0" + "Dgrave_accent\0" + "diaeresis\0" + "diamond\0" + "digitspace\0" + "dintegral\0" + "division\0" + "dollar\0" + "DongSign\0" + "doubbaselinedot\0" + "doubleacute\0" + "doubledagger\0" + "doublelowquotemark\0" + "Down\0" + "downarrow\0" + "downcaret\0" + "downshoe\0" + "downstile\0" + "downtack\0" + "DRemove\0" + "Dring_accent\0" + "Dstroke\0" + "dstroke\0" + "Dtilde\0" + "E\0" + "e\0" + "Eabovedot\0" + "eabovedot\0" + "Eacute\0" + "eacute\0" + "Ebelowdot\0" + "ebelowdot\0" + "Ecaron\0" + "ecaron\0" + "Ecircumflex\0" + "ecircumflex\0" + "Ecircumflexacute\0" + "ecircumflexacute\0" + "Ecircumflexbelowdot\0" + "ecircumflexbelowdot\0" + "Ecircumflexgrave\0" + "ecircumflexgrave\0" + "Ecircumflexhook\0" + "ecircumflexhook\0" + "Ecircumflextilde\0" + "ecircumflextilde\0" + "EcuSign\0" + "Ediaeresis\0" + "ediaeresis\0" + "Egrave\0" + "egrave\0" + "Ehook\0" + "ehook\0" + "eightsubscript\0" + "eightsuperior\0" + "Eisu_Shift\0" + "Eisu_toggle\0" + "elementof\0" + "ellipsis\0" + "em3space\0" + "em4space\0" + "Emacron\0" + "emacron\0" + "emdash\0" + "emfilledcircle\0" + "emfilledrect\0" + "emopencircle\0" + "emopenrectangle\0" + "emptyset\0" + "emspace\0" + "End\0" + "endash\0" + "enfilledcircbullet\0" + "enfilledsqbullet\0" + "ENG\0" + "eng\0" + "enopencircbullet\0" + "enopensquarebullet\0" + "enspace\0" + "Eogonek\0" + "eogonek\0" + "equal\0" + "Escape\0" + "ETH\0" + "Eth\0" + "eth\0" + "Etilde\0" + "etilde\0" + "EuroSign\0" + "exclam\0" + "exclamdown\0" + "Execute\0" + "Ext16bit_L\0" + "Ext16bit_R\0" + "EZH\0" + "ezh\0" + "F\0" + "f\0" + "F1\0" + "F10\0" + "F11\0" + "F12\0" + "F13\0" + "F14\0" + "F15\0" + "F16\0" + "F17\0" + "F18\0" + "F19\0" + "F2\0" + "F20\0" + "F21\0" + "F22\0" + "F23\0" + "F24\0" + "F25\0" + "F26\0" + "F27\0" + "F28\0" + "F29\0" + "F3\0" + "F30\0" + "F31\0" + "F32\0" + "F33\0" + "F34\0" + "F35\0" + "F4\0" + "F5\0" + "F6\0" + "F7\0" + "F8\0" + "F9\0" + "Fabovedot\0" + "fabovedot\0" + "Farsi_0\0" + "Farsi_1\0" + "Farsi_2\0" + "Farsi_3\0" + "Farsi_4\0" + "Farsi_5\0" + "Farsi_6\0" + "Farsi_7\0" + "Farsi_8\0" + "Farsi_9\0" + "Farsi_yeh\0" + "femalesymbol\0" + "ff\0" + "FFrancSign\0" + "figdash\0" + "filledlefttribullet\0" + "filledrectbullet\0" + "filledrighttribullet\0" + "filledtribulletdown\0" + "filledtribulletup\0" + "Find\0" + "First_Virtual_Screen\0" + "fiveeighths\0" + "fivesixths\0" + "fivesubscript\0" + "fivesuperior\0" + "fourfifths\0" + "foursubscript\0" + "foursuperior\0" + "fourthroot\0" + "function\0" + "G\0" + "g\0" + "Gabovedot\0" + "gabovedot\0" + "Gbreve\0" + "gbreve\0" + "Gcaron\0" + "gcaron\0" + "Gcedilla\0" + "gcedilla\0" + "Gcircumflex\0" + "gcircumflex\0" + "Georgian_an\0" + "Georgian_ban\0" + "Georgian_can\0" + "Georgian_char\0" + "Georgian_chin\0" + "Georgian_cil\0" + "Georgian_don\0" + "Georgian_en\0" + "Georgian_fi\0" + "Georgian_gan\0" + "Georgian_ghan\0" + "Georgian_hae\0" + "Georgian_har\0" + "Georgian_he\0" + "Georgian_hie\0" + "Georgian_hoe\0" + "Georgian_in\0" + "Georgian_jhan\0" + "Georgian_jil\0" + "Georgian_kan\0" + "Georgian_khar\0" + "Georgian_las\0" + "Georgian_man\0" + "Georgian_nar\0" + "Georgian_on\0" + "Georgian_par\0" + "Georgian_phar\0" + "Georgian_qar\0" + "Georgian_rae\0" + "Georgian_san\0" + "Georgian_shin\0" + "Georgian_tan\0" + "Georgian_tar\0" + "Georgian_un\0" + "Georgian_vin\0" + "Georgian_we\0" + "Georgian_xan\0" + "Georgian_zen\0" + "Georgian_zhar\0" + "grave\0" + "greater\0" + "greaterthanequal\0" + "Greek_accentdieresis\0" + "Greek_ALPHA\0" + "Greek_alpha\0" + "Greek_ALPHAaccent\0" + "Greek_alphaaccent\0" + "Greek_BETA\0" + "Greek_beta\0" + "Greek_CHI\0" + "Greek_chi\0" + "Greek_DELTA\0" + "Greek_delta\0" + "Greek_EPSILON\0" + "Greek_epsilon\0" + "Greek_EPSILONaccent\0" + "Greek_epsilonaccent\0" + "Greek_ETA\0" + "Greek_eta\0" + "Greek_ETAaccent\0" + "Greek_etaaccent\0" + "Greek_finalsmallsigma\0" + "Greek_GAMMA\0" + "Greek_gamma\0" + "Greek_horizbar\0" + "Greek_IOTA\0" + "Greek_iota\0" + "Greek_IOTAaccent\0" + "Greek_iotaaccent\0" + "Greek_iotaaccentdieresis\0" + "Greek_IOTAdiaeresis\0" + "Greek_IOTAdieresis\0" + "Greek_iotadieresis\0" + "Greek_KAPPA\0" + "Greek_kappa\0" + "Greek_LAMBDA\0" + "Greek_lambda\0" + "Greek_LAMDA\0" + "Greek_lamda\0" + "Greek_MU\0" + "Greek_mu\0" + "Greek_NU\0" + "Greek_nu\0" + "Greek_OMEGA\0" + "Greek_omega\0" + "Greek_OMEGAaccent\0" + "Greek_omegaaccent\0" + "Greek_OMICRON\0" + "Greek_omicron\0" + "Greek_OMICRONaccent\0" + "Greek_omicronaccent\0" + "Greek_PHI\0" + "Greek_phi\0" + "Greek_PI\0" + "Greek_pi\0" + "Greek_PSI\0" + "Greek_psi\0" + "Greek_RHO\0" + "Greek_rho\0" + "Greek_SIGMA\0" + "Greek_sigma\0" + "Greek_switch\0" + "Greek_TAU\0" + "Greek_tau\0" + "Greek_THETA\0" + "Greek_theta\0" + "Greek_UPSILON\0" + "Greek_upsilon\0" + "Greek_UPSILONaccent\0" + "Greek_upsilonaccent\0" + "Greek_upsilonaccentdieresis\0" + "Greek_UPSILONdieresis\0" + "Greek_upsilondieresis\0" + "Greek_XI\0" + "Greek_xi\0" + "Greek_ZETA\0" + "Greek_zeta\0" + "guilder\0" + "guillemotleft\0" + "guillemotright\0" + "H\0" + "h\0" + "hairspace\0" + "Hangul\0" + "Hangul_A\0" + "Hangul_AE\0" + "Hangul_AraeA\0" + "Hangul_AraeAE\0" + "Hangul_Banja\0" + "Hangul_Cieuc\0" + "Hangul_Codeinput\0" + "Hangul_Dikeud\0" + "Hangul_E\0" + "Hangul_End\0" + "Hangul_EO\0" + "Hangul_EU\0" + "Hangul_Hanja\0" + "Hangul_Hieuh\0" + "Hangul_I\0" + "Hangul_Ieung\0" + "Hangul_J_Cieuc\0" + "Hangul_J_Dikeud\0" + "Hangul_J_Hieuh\0" + "Hangul_J_Ieung\0" + "Hangul_J_Jieuj\0" + "Hangul_J_Khieuq\0" + "Hangul_J_Kiyeog\0" + "Hangul_J_KiyeogSios\0" + "Hangul_J_KkogjiDalrinIeung\0" + "Hangul_J_Mieum\0" + "Hangul_J_Nieun\0" + "Hangul_J_NieunHieuh\0" + "Hangul_J_NieunJieuj\0" + "Hangul_J_PanSios\0" + "Hangul_J_Phieuf\0" + "Hangul_J_Pieub\0" + "Hangul_J_PieubSios\0" + "Hangul_J_Rieul\0" + "Hangul_J_RieulHieuh\0" + "Hangul_J_RieulKiyeog\0" + "Hangul_J_RieulMieum\0" + "Hangul_J_RieulPhieuf\0" + "Hangul_J_RieulPieub\0" + "Hangul_J_RieulSios\0" + "Hangul_J_RieulTieut\0" + "Hangul_J_Sios\0" + "Hangul_J_SsangKiyeog\0" + "Hangul_J_SsangSios\0" + "Hangul_J_Tieut\0" + "Hangul_J_YeorinHieuh\0" + "Hangul_Jamo\0" + "Hangul_Jeonja\0" + "Hangul_Jieuj\0" + "Hangul_Khieuq\0" + "Hangul_Kiyeog\0" + "Hangul_KiyeogSios\0" + "Hangul_KkogjiDalrinIeung\0" + "Hangul_Mieum\0" + "Hangul_MultipleCandidate\0" + "Hangul_Nieun\0" + "Hangul_NieunHieuh\0" + "Hangul_NieunJieuj\0" + "Hangul_O\0" + "Hangul_OE\0" + "Hangul_PanSios\0" + "Hangul_Phieuf\0" + "Hangul_Pieub\0" + "Hangul_PieubSios\0" + "Hangul_PostHanja\0" + "Hangul_PreHanja\0" + "Hangul_PreviousCandidate\0" + "Hangul_Rieul\0" + "Hangul_RieulHieuh\0" + "Hangul_RieulKiyeog\0" + "Hangul_RieulMieum\0" + "Hangul_RieulPhieuf\0" + "Hangul_RieulPieub\0" + "Hangul_RieulSios\0" + "Hangul_RieulTieut\0" + "Hangul_RieulYeorinHieuh\0" + "Hangul_Romaja\0" + "Hangul_SingleCandidate\0" + "Hangul_Sios\0" + "Hangul_Special\0" + "Hangul_SsangDikeud\0" + "Hangul_SsangJieuj\0" + "Hangul_SsangKiyeog\0" + "Hangul_SsangPieub\0" + "Hangul_SsangSios\0" + "Hangul_Start\0" + "Hangul_SunkyeongeumMieum\0" + "Hangul_SunkyeongeumPhieuf\0" + "Hangul_SunkyeongeumPieub\0" + "Hangul_switch\0" + "Hangul_Tieut\0" + "Hangul_U\0" + "Hangul_WA\0" + "Hangul_WAE\0" + "Hangul_WE\0" + "Hangul_WEO\0" + "Hangul_WI\0" + "Hangul_YA\0" + "Hangul_YAE\0" + "Hangul_YE\0" + "Hangul_YEO\0" + "Hangul_YeorinHieuh\0" + "Hangul_YI\0" + "Hangul_YO\0" + "Hangul_YU\0" + "Hankaku\0" + "Hcircumflex\0" + "hcircumflex\0" + "heart\0" + "hebrew_aleph\0" + "hebrew_ayin\0" + "hebrew_bet\0" + "hebrew_beth\0" + "hebrew_chet\0" + "hebrew_dalet\0" + "hebrew_daleth\0" + "hebrew_doublelowline\0" + "hebrew_finalkaph\0" + "hebrew_finalmem\0" + "hebrew_finalnun\0" + "hebrew_finalpe\0" + "hebrew_finalzade\0" + "hebrew_finalzadi\0" + "hebrew_gimel\0" + "hebrew_gimmel\0" + "hebrew_he\0" + "hebrew_het\0" + "hebrew_kaph\0" + "hebrew_kuf\0" + "hebrew_lamed\0" + "hebrew_mem\0" + "hebrew_nun\0" + "hebrew_pe\0" + "hebrew_qoph\0" + "hebrew_resh\0" + "hebrew_samech\0" + "hebrew_samekh\0" + "hebrew_shin\0" + "Hebrew_switch\0" + "hebrew_taf\0" + "hebrew_taw\0" + "hebrew_tet\0" + "hebrew_teth\0" + "hebrew_waw\0" + "hebrew_yod\0" + "hebrew_zade\0" + "hebrew_zadi\0" + "hebrew_zain\0" + "hebrew_zayin\0" + "Help\0" + "Henkan\0" + "Henkan_Mode\0" + "hexagram\0" + "Hiragana\0" + "Hiragana_Katakana\0" + "Home\0" + "horizconnector\0" + "horizlinescan1\0" + "horizlinescan3\0" + "horizlinescan5\0" + "horizlinescan7\0" + "horizlinescan9\0" + "hpBackTab\0" + "hpblock\0" + "hpClearLine\0" + "hpDeleteChar\0" + "hpDeleteLine\0" + "hpguilder\0" + "hpInsertChar\0" + "hpInsertLine\0" + "hpIO\0" + "hpKP_BackTab\0" + "hplira\0" + "hplongminus\0" + "hpModelock1\0" + "hpModelock2\0" + "hpmute_acute\0" + "hpmute_asciicircum\0" + "hpmute_asciitilde\0" + "hpmute_diaeresis\0" + "hpmute_grave\0" + "hpReset\0" + "hpSystem\0" + "hpUser\0" + "hpYdiaeresis\0" + "Hstroke\0" + "hstroke\0" + "ht\0" + "Hyper_L\0" + "Hyper_R\0" + "hyphen\0" + "I\0" + "i\0" + "Iabovedot\0" + "Iacute\0" + "iacute\0" + "Ibelowdot\0" + "ibelowdot\0" + "Ibreve\0" + "ibreve\0" + "Icircumflex\0" + "icircumflex\0" + "identical\0" + "Idiaeresis\0" + "idiaeresis\0" + "idotless\0" + "ifonlyif\0" + "Igrave\0" + "igrave\0" + "Ihook\0" + "ihook\0" + "Imacron\0" + "imacron\0" + "implies\0" + "includedin\0" + "includes\0" + "infinity\0" + "Insert\0" + "InsertChar\0" + "InsertLine\0" + "integral\0" + "intersection\0" + "IO\0" + "Iogonek\0" + "iogonek\0" + "ISO_Center_Object\0" + "ISO_Continuous_Underline\0" + "ISO_Discontinuous_Underline\0" + "ISO_Emphasize\0" + "ISO_Enter\0" + "ISO_Fast_Cursor_Down\0" + "ISO_Fast_Cursor_Left\0" + "ISO_Fast_Cursor_Right\0" + "ISO_Fast_Cursor_Up\0" + "ISO_First_Group\0" + "ISO_First_Group_Lock\0" + "ISO_Group_Latch\0" + "ISO_Group_Lock\0" + "ISO_Group_Shift\0" + "ISO_Last_Group\0" + "ISO_Last_Group_Lock\0" + "ISO_Left_Tab\0" + "ISO_Level2_Latch\0" + "ISO_Level3_Latch\0" + "ISO_Level3_Lock\0" + "ISO_Level3_Shift\0" + "ISO_Level5_Latch\0" + "ISO_Level5_Lock\0" + "ISO_Level5_Shift\0" + "ISO_Lock\0" + "ISO_Move_Line_Down\0" + "ISO_Move_Line_Up\0" + "ISO_Next_Group\0" + "ISO_Next_Group_Lock\0" + "ISO_Partial_Line_Down\0" + "ISO_Partial_Line_Up\0" + "ISO_Partial_Space_Left\0" + "ISO_Partial_Space_Right\0" + "ISO_Prev_Group\0" + "ISO_Prev_Group_Lock\0" + "ISO_Release_Both_Margins\0" + "ISO_Release_Margin_Left\0" + "ISO_Release_Margin_Right\0" + "ISO_Set_Margin_Left\0" + "ISO_Set_Margin_Right\0" + "Itilde\0" + "itilde\0" + "J\0" + "j\0" + "Jcircumflex\0" + "jcircumflex\0" + "jot\0" + "K\0" + "k\0" + "kana_a\0" + "kana_A\0" + "kana_CHI\0" + "kana_closingbracket\0" + "kana_comma\0" + "kana_conjunctive\0" + "kana_e\0" + "kana_E\0" + "kana_FU\0" + "kana_fullstop\0" + "kana_HA\0" + "kana_HE\0" + "kana_HI\0" + "kana_HO\0" + "kana_HU\0" + "kana_i\0" + "kana_I\0" + "kana_KA\0" + "kana_KE\0" + "kana_KI\0" + "kana_KO\0" + "kana_KU\0" + "Kana_Lock\0" + "kana_MA\0" + "kana_ME\0" + "kana_MI\0" + "kana_middledot\0" + "kana_MO\0" + "kana_MU\0" + "kana_N\0" + "kana_NA\0" + "kana_NE\0" + "kana_NI\0" + "kana_NO\0" + "kana_NU\0" + "kana_o\0" + "kana_O\0" + "kana_openingbracket\0" + "kana_RA\0" + "kana_RE\0" + "kana_RI\0" + "kana_RO\0" + "kana_RU\0" + "kana_SA\0" + "kana_SE\0" + "kana_SHI\0" + "Kana_Shift\0" + "kana_SO\0" + "kana_SU\0" + "kana_switch\0" + "kana_TA\0" + "kana_TE\0" + "kana_TI\0" + "kana_TO\0" + "kana_tsu\0" + "kana_TSU\0" + "kana_tu\0" + "kana_TU\0" + "kana_u\0" + "kana_U\0" + "kana_WA\0" + "kana_WO\0" + "kana_ya\0" + "kana_YA\0" + "kana_yo\0" + "kana_YO\0" + "kana_yu\0" + "kana_YU\0" + "Kanji\0" + "Kanji_Bangou\0" + "kappa\0" + "Katakana\0" + "Kcedilla\0" + "kcedilla\0" + "Korean_Won\0" + "KP_0\0" + "KP_1\0" + "KP_2\0" + "KP_3\0" + "KP_4\0" + "KP_5\0" + "KP_6\0" + "KP_7\0" + "KP_8\0" + "KP_9\0" + "KP_Add\0" + "KP_BackTab\0" + "KP_Begin\0" + "KP_Decimal\0" + "KP_Delete\0" + "KP_Divide\0" + "KP_Down\0" + "KP_End\0" + "KP_Enter\0" + "KP_Equal\0" + "KP_F1\0" + "KP_F2\0" + "KP_F3\0" + "KP_F4\0" + "KP_Home\0" + "KP_Insert\0" + "KP_Left\0" + "KP_Multiply\0" + "KP_Next\0" + "KP_Page_Down\0" + "KP_Page_Up\0" + "KP_Prior\0" + "KP_Right\0" + "KP_Separator\0" + "KP_Space\0" + "KP_Subtract\0" + "KP_Tab\0" + "KP_Up\0" + "kra\0" + "L\0" + "l\0" + "L1\0" + "L10\0" + "L2\0" + "L3\0" + "L4\0" + "L5\0" + "L6\0" + "L7\0" + "L8\0" + "L9\0" + "Lacute\0" + "lacute\0" + "Last_Virtual_Screen\0" + "latincross\0" + "Lbelowdot\0" + "lbelowdot\0" + "Lcaron\0" + "lcaron\0" + "Lcedilla\0" + "lcedilla\0" + "Left\0" + "leftanglebracket\0" + "leftarrow\0" + "leftcaret\0" + "leftdoublequotemark\0" + "leftmiddlecurlybrace\0" + "leftopentriangle\0" + "leftpointer\0" + "leftradical\0" + "leftshoe\0" + "leftsinglequotemark\0" + "leftt\0" + "lefttack\0" + "less\0" + "lessthanequal\0" + "lf\0" + "Linefeed\0" + "lira\0" + "LiraSign\0" + "logicaland\0" + "logicalor\0" + "longminus\0" + "lowleftcorner\0" + "lowrightcorner\0" + "Lstroke\0" + "lstroke\0" + "M\0" + "m\0" + "Mabovedot\0" + "mabovedot\0" + "Macedonia_dse\0" + "Macedonia_DSE\0" + "Macedonia_gje\0" + "Macedonia_GJE\0" + "Macedonia_kje\0" + "Macedonia_KJE\0" + "macron\0" + "Mae_Koho\0" + "malesymbol\0" + "maltesecross\0" + "marker\0" + "masculine\0" + "Massyo\0" + "Menu\0" + "Meta_L\0" + "Meta_R\0" + "MillSign\0" + "minus\0" + "minutes\0" + "Mode_switch\0" + "MouseKeys_Accel_Enable\0" + "MouseKeys_Enable\0" + "mu\0" + "Muhenkan\0" + "Multi_key\0" + "MultipleCandidate\0" + "multiply\0" + "musicalflat\0" + "musicalsharp\0" + "mute_acute\0" + "mute_asciicircum\0" + "mute_asciitilde\0" + "mute_diaeresis\0" + "mute_grave\0" + "N\0" + "n\0" + "nabla\0" + "Nacute\0" + "nacute\0" + "NairaSign\0" + "Ncaron\0" + "ncaron\0" + "Ncedilla\0" + "ncedilla\0" + "NewSheqelSign\0" + "Next\0" + "Next_Virtual_Screen\0" + "ninesubscript\0" + "ninesuperior\0" + "nl\0" + "nobreakspace\0" + "NoSymbol\0" + "notapproxeq\0" + "notelementof\0" + "notequal\0" + "notidentical\0" + "notsign\0" + "Ntilde\0" + "ntilde\0" + "Num_Lock\0" + "numbersign\0" + "numerosign\0" + "O\0" + "o\0" + "Oacute\0" + "oacute\0" + "Obarred\0" + "obarred\0" + "Obelowdot\0" + "obelowdot\0" + "Ocaron\0" + "ocaron\0" + "Ocircumflex\0" + "ocircumflex\0" + "Ocircumflexacute\0" + "ocircumflexacute\0" + "Ocircumflexbelowdot\0" + "ocircumflexbelowdot\0" + "Ocircumflexgrave\0" + "ocircumflexgrave\0" + "Ocircumflexhook\0" + "ocircumflexhook\0" + "Ocircumflextilde\0" + "ocircumflextilde\0" + "Odiaeresis\0" + "odiaeresis\0" + "Odoubleacute\0" + "odoubleacute\0" + "OE\0" + "oe\0" + "ogonek\0" + "Ograve\0" + "ograve\0" + "Ohook\0" + "ohook\0" + "Ohorn\0" + "ohorn\0" + "Ohornacute\0" + "ohornacute\0" + "Ohornbelowdot\0" + "ohornbelowdot\0" + "Ohorngrave\0" + "ohorngrave\0" + "Ohornhook\0" + "ohornhook\0" + "Ohorntilde\0" + "ohorntilde\0" + "Omacron\0" + "omacron\0" + "oneeighth\0" + "onefifth\0" + "onehalf\0" + "onequarter\0" + "onesixth\0" + "onesubscript\0" + "onesuperior\0" + "onethird\0" + "Ooblique\0" + "ooblique\0" + "openrectbullet\0" + "openstar\0" + "opentribulletdown\0" + "opentribulletup\0" + "ordfeminine\0" + "osfActivate\0" + "osfAddMode\0" + "osfBackSpace\0" + "osfBackTab\0" + "osfBeginData\0" + "osfBeginLine\0" + "osfCancel\0" + "osfClear\0" + "osfCopy\0" + "osfCut\0" + "osfDelete\0" + "osfDeselectAll\0" + "osfDown\0" + "osfEndData\0" + "osfEndLine\0" + "osfEscape\0" + "osfExtend\0" + "osfHelp\0" + "osfInsert\0" + "osfLeft\0" + "osfMenu\0" + "osfMenuBar\0" + "osfNextField\0" + "osfNextMenu\0" + "osfPageDown\0" + "osfPageLeft\0" + "osfPageRight\0" + "osfPageUp\0" + "osfPaste\0" + "osfPrevField\0" + "osfPrevMenu\0" + "osfPrimaryPaste\0" + "osfQuickPaste\0" + "osfReselect\0" + "osfRestore\0" + "osfRight\0" + "osfSelect\0" + "osfSelectAll\0" + "osfUndo\0" + "osfUp\0" + "Oslash\0" + "oslash\0" + "Otilde\0" + "otilde\0" + "overbar\0" + "Overlay1_Enable\0" + "Overlay2_Enable\0" + "overline\0" + "P\0" + "p\0" + "Pabovedot\0" + "pabovedot\0" + "Page_Down\0" + "Page_Up\0" + "paragraph\0" + "parenleft\0" + "parenright\0" + "partdifferential\0" + "partialderivative\0" + "Pause\0" + "percent\0" + "period\0" + "periodcentered\0" + "permille\0" + "PesetaSign\0" + "phonographcopyright\0" + "plus\0" + "plusminus\0" + "Pointer_Accelerate\0" + "Pointer_Button1\0" + "Pointer_Button2\0" + "Pointer_Button3\0" + "Pointer_Button4\0" + "Pointer_Button5\0" + "Pointer_Button_Dflt\0" + "Pointer_DblClick1\0" + "Pointer_DblClick2\0" + "Pointer_DblClick3\0" + "Pointer_DblClick4\0" + "Pointer_DblClick5\0" + "Pointer_DblClick_Dflt\0" + "Pointer_DfltBtnNext\0" + "Pointer_DfltBtnPrev\0" + "Pointer_Down\0" + "Pointer_DownLeft\0" + "Pointer_DownRight\0" + "Pointer_Drag1\0" + "Pointer_Drag2\0" + "Pointer_Drag3\0" + "Pointer_Drag4\0" + "Pointer_Drag5\0" + "Pointer_Drag_Dflt\0" + "Pointer_EnableKeys\0" + "Pointer_Left\0" + "Pointer_Right\0" + "Pointer_Up\0" + "Pointer_UpLeft\0" + "Pointer_UpRight\0" + "prescription\0" + "Prev_Virtual_Screen\0" + "PreviousCandidate\0" + "Print\0" + "Prior\0" + "prolongedsound\0" + "punctspace\0" + "Q\0" + "q\0" + "quad\0" + "question\0" + "questiondown\0" + "quotedbl\0" + "quoteleft\0" + "quoteright\0" + "R\0" + "r\0" + "R1\0" + "R10\0" + "R11\0" + "R12\0" + "R13\0" + "R14\0" + "R15\0" + "R2\0" + "R3\0" + "R4\0" + "R5\0" + "R6\0" + "R7\0" + "R8\0" + "R9\0" + "Racute\0" + "racute\0" + "radical\0" + "Rcaron\0" + "rcaron\0" + "Rcedilla\0" + "rcedilla\0" + "Redo\0" + "registered\0" + "RepeatKeys_Enable\0" + "Reset\0" + "Return\0" + "Right\0" + "rightanglebracket\0" + "rightarrow\0" + "rightcaret\0" + "rightdoublequotemark\0" + "rightmiddlecurlybrace\0" + "rightmiddlesummation\0" + "rightopentriangle\0" + "rightpointer\0" + "rightshoe\0" + "rightsinglequotemark\0" + "rightt\0" + "righttack\0" + "Romaji\0" + "RupeeSign\0" + "S\0" + "s\0" + "Sabovedot\0" + "sabovedot\0" + "Sacute\0" + "sacute\0" + "Scaron\0" + "scaron\0" + "Scedilla\0" + "scedilla\0" + "SCHWA\0" + "schwa\0" + "Scircumflex\0" + "scircumflex\0" + "script_switch\0" + "Scroll_Lock\0" + "seconds\0" + "section\0" + "Select\0" + "semicolon\0" + "semivoicedsound\0" + "Serbian_dje\0" + "Serbian_DJE\0" + "Serbian_dze\0" + "Serbian_DZE\0" + "Serbian_je\0" + "Serbian_JE\0" + "Serbian_lje\0" + "Serbian_LJE\0" + "Serbian_nje\0" + "Serbian_NJE\0" + "Serbian_tshe\0" + "Serbian_TSHE\0" + "seveneighths\0" + "sevensubscript\0" + "sevensuperior\0" + "Shift_L\0" + "Shift_Lock\0" + "Shift_R\0" + "signaturemark\0" + "signifblank\0" + "similarequal\0" + "SingleCandidate\0" + "singlelowquotemark\0" + "Sinh_a\0" + "Sinh_aa\0" + "Sinh_aa2\0" + "Sinh_ae\0" + "Sinh_ae2\0" + "Sinh_aee\0" + "Sinh_aee2\0" + "Sinh_ai\0" + "Sinh_ai2\0" + "Sinh_al\0" + "Sinh_au\0" + "Sinh_au2\0" + "Sinh_ba\0" + "Sinh_bha\0" + "Sinh_ca\0" + "Sinh_cha\0" + "Sinh_dda\0" + "Sinh_ddha\0" + "Sinh_dha\0" + "Sinh_dhha\0" + "Sinh_e\0" + "Sinh_e2\0" + "Sinh_ee\0" + "Sinh_ee2\0" + "Sinh_fa\0" + "Sinh_ga\0" + "Sinh_gha\0" + "Sinh_h2\0" + "Sinh_ha\0" + "Sinh_i\0" + "Sinh_i2\0" + "Sinh_ii\0" + "Sinh_ii2\0" + "Sinh_ja\0" + "Sinh_jha\0" + "Sinh_jnya\0" + "Sinh_ka\0" + "Sinh_kha\0" + "Sinh_kunddaliya\0" + "Sinh_la\0" + "Sinh_lla\0" + "Sinh_lu\0" + "Sinh_lu2\0" + "Sinh_luu\0" + "Sinh_luu2\0" + "Sinh_ma\0" + "Sinh_mba\0" + "Sinh_na\0" + "Sinh_ndda\0" + "Sinh_ndha\0" + "Sinh_ng\0" + "Sinh_ng2\0" + "Sinh_nga\0" + "Sinh_nja\0" + "Sinh_nna\0" + "Sinh_nya\0" + "Sinh_o\0" + "Sinh_o2\0" + "Sinh_oo\0" + "Sinh_oo2\0" + "Sinh_pa\0" + "Sinh_pha\0" + "Sinh_ra\0" + "Sinh_ri\0" + "Sinh_rii\0" + "Sinh_ru2\0" + "Sinh_ruu2\0" + "Sinh_sa\0" + "Sinh_sha\0" + "Sinh_ssha\0" + "Sinh_tha\0" + "Sinh_thha\0" + "Sinh_tta\0" + "Sinh_ttha\0" + "Sinh_u\0" + "Sinh_u2\0" + "Sinh_uu\0" + "Sinh_uu2\0" + "Sinh_va\0" + "Sinh_ya\0" + "sixsubscript\0" + "sixsuperior\0" + "slash\0" + "SlowKeys_Enable\0" + "soliddiamond\0" + "space\0" + "squareroot\0" + "ssharp\0" + "sterling\0" + "StickyKeys_Enable\0" + "stricteq\0" + "SunAgain\0" + "SunAltGraph\0" + "SunAudioLowerVolume\0" + "SunAudioMute\0" + "SunAudioRaiseVolume\0" + "SunCompose\0" + "SunCopy\0" + "SunCut\0" + "SunF36\0" + "SunF37\0" + "SunFA_Acute\0" + "SunFA_Cedilla\0" + "SunFA_Circum\0" + "SunFA_Diaeresis\0" + "SunFA_Grave\0" + "SunFA_Tilde\0" + "SunFind\0" + "SunFront\0" + "SunOpen\0" + "SunPageDown\0" + "SunPageUp\0" + "SunPaste\0" + "SunPowerSwitch\0" + "SunPowerSwitchShift\0" + "SunPrint_Screen\0" + "SunProps\0" + "SunStop\0" + "SunSys_Req\0" + "SunUndo\0" + "SunVideoDegauss\0" + "SunVideoLowerBrightness\0" + "SunVideoRaiseBrightness\0" + "Super_L\0" + "Super_R\0" + "Sys_Req\0" + "System\0" + "T\0" + "t\0" + "Tab\0" + "Tabovedot\0" + "tabovedot\0" + "Tcaron\0" + "tcaron\0" + "Tcedilla\0" + "tcedilla\0" + "telephone\0" + "telephonerecorder\0" + "Terminate_Server\0" + "Thai_baht\0" + "Thai_bobaimai\0" + "Thai_chochan\0" + "Thai_chochang\0" + "Thai_choching\0" + "Thai_chochoe\0" + "Thai_dochada\0" + "Thai_dodek\0" + "Thai_fofa\0" + "Thai_fofan\0" + "Thai_hohip\0" + "Thai_honokhuk\0" + "Thai_khokhai\0" + "Thai_khokhon\0" + "Thai_khokhuat\0" + "Thai_khokhwai\0" + "Thai_khorakhang\0" + "Thai_kokai\0" + "Thai_lakkhangyao\0" + "Thai_lekchet\0" + "Thai_lekha\0" + "Thai_lekhok\0" + "Thai_lekkao\0" + "Thai_leknung\0" + "Thai_lekpaet\0" + "Thai_leksam\0" + "Thai_leksi\0" + "Thai_leksong\0" + "Thai_leksun\0" + "Thai_lochula\0" + "Thai_loling\0" + "Thai_lu\0" + "Thai_maichattawa\0" + "Thai_maiek\0" + "Thai_maihanakat\0" + "Thai_maihanakat_maitho\0" + "Thai_maitaikhu\0" + "Thai_maitho\0" + "Thai_maitri\0" + "Thai_maiyamok\0" + "Thai_moma\0" + "Thai_ngongu\0" + "Thai_nikhahit\0" + "Thai_nonen\0" + "Thai_nonu\0" + "Thai_oang\0" + "Thai_paiyannoi\0" + "Thai_phinthu\0" + "Thai_phophan\0" + "Thai_phophung\0" + "Thai_phosamphao\0" + "Thai_popla\0" + "Thai_rorua\0" + "Thai_ru\0" + "Thai_saraa\0" + "Thai_saraaa\0" + "Thai_saraae\0" + "Thai_saraaimaimalai\0" + "Thai_saraaimaimuan\0" + "Thai_saraam\0" + "Thai_sarae\0" + "Thai_sarai\0" + "Thai_saraii\0" + "Thai_sarao\0" + "Thai_sarau\0" + "Thai_saraue\0" + "Thai_sarauee\0" + "Thai_sarauu\0" + "Thai_sorusi\0" + "Thai_sosala\0" + "Thai_soso\0" + "Thai_sosua\0" + "Thai_thanthakhat\0" + "Thai_thonangmontho\0" + "Thai_thophuthao\0" + "Thai_thothahan\0" + "Thai_thothan\0" + "Thai_thothong\0" + "Thai_thothung\0" + "Thai_topatak\0" + "Thai_totao\0" + "Thai_wowaen\0" + "Thai_yoyak\0" + "Thai_yoying\0" + "therefore\0" + "thinspace\0" + "THORN\0" + "Thorn\0" + "thorn\0" + "threeeighths\0" + "threefifths\0" + "threequarters\0" + "threesubscript\0" + "threesuperior\0" + "tintegral\0" + "topintegral\0" + "topleftparens\0" + "topleftradical\0" + "topleftsqbracket\0" + "topleftsummation\0" + "toprightparens\0" + "toprightsqbracket\0" + "toprightsummation\0" + "topt\0" + "topvertsummationconnector\0" + "Touroku\0" + "trademark\0" + "trademarkincircle\0" + "Tslash\0" + "tslash\0" + "twofifths\0" + "twosubscript\0" + "twosuperior\0" + "twothirds\0" + "U\0" + "u\0" + "Uacute\0" + "uacute\0" + "Ubelowdot\0" + "ubelowdot\0" + "Ubreve\0" + "ubreve\0" + "Ucircumflex\0" + "ucircumflex\0" + "Udiaeresis\0" + "udiaeresis\0" + "Udoubleacute\0" + "udoubleacute\0" + "Ugrave\0" + "ugrave\0" + "Uhook\0" + "uhook\0" + "Uhorn\0" + "uhorn\0" + "Uhornacute\0" + "uhornacute\0" + "Uhornbelowdot\0" + "uhornbelowdot\0" + "Uhorngrave\0" + "uhorngrave\0" + "Uhornhook\0" + "uhornhook\0" + "Uhorntilde\0" + "uhorntilde\0" + "Ukrainian_ghe_with_upturn\0" + "Ukrainian_GHE_WITH_UPTURN\0" + "Ukrainian_i\0" + "Ukrainian_I\0" + "Ukrainian_ie\0" + "Ukrainian_IE\0" + "Ukrainian_yi\0" + "Ukrainian_YI\0" + "Ukranian_i\0" + "Ukranian_I\0" + "Ukranian_je\0" + "Ukranian_JE\0" + "Ukranian_yi\0" + "Ukranian_YI\0" + "Umacron\0" + "umacron\0" + "underbar\0" + "underscore\0" + "Undo\0" + "union\0" + "Uogonek\0" + "uogonek\0" + "Up\0" + "uparrow\0" + "upcaret\0" + "upleftcorner\0" + "uprightcorner\0" + "upshoe\0" + "upstile\0" + "uptack\0" + "Uring\0" + "uring\0" + "User\0" + "Utilde\0" + "utilde\0" + "V\0" + "v\0" + "variation\0" + "vertbar\0" + "vertconnector\0" + "voicedsound\0" + "VoidSymbol\0" + "vt\0" + "W\0" + "w\0" + "Wacute\0" + "wacute\0" + "Wcircumflex\0" + "wcircumflex\0" + "Wdiaeresis\0" + "wdiaeresis\0" + "Wgrave\0" + "wgrave\0" + "WonSign\0" + "X\0" + "x\0" + "Xabovedot\0" + "xabovedot\0" + "XF86AddFavorite\0" + "XF86ApplicationLeft\0" + "XF86ApplicationRight\0" + "XF86AudioCycleTrack\0" + "XF86AudioForward\0" + "XF86AudioLowerVolume\0" + "XF86AudioMedia\0" + "XF86AudioMicMute\0" + "XF86AudioMute\0" + "XF86AudioNext\0" + "XF86AudioPause\0" + "XF86AudioPlay\0" + "XF86AudioPrev\0" + "XF86AudioRaiseVolume\0" + "XF86AudioRandomPlay\0" + "XF86AudioRecord\0" + "XF86AudioRepeat\0" + "XF86AudioRewind\0" + "XF86AudioStop\0" + "XF86Away\0" + "XF86Back\0" + "XF86BackForward\0" + "XF86Battery\0" + "XF86Blue\0" + "XF86Bluetooth\0" + "XF86Book\0" + "XF86BrightnessAdjust\0" + "XF86Calculater\0" + "XF86Calculator\0" + "XF86Calendar\0" + "XF86CD\0" + "XF86Clear\0" + "XF86ClearGrab\0" + "XF86Close\0" + "XF86Community\0" + "XF86ContrastAdjust\0" + "XF86Copy\0" + "XF86Cut\0" + "XF86CycleAngle\0" + "XF86Display\0" + "XF86Documents\0" + "XF86DOS\0" + "XF86Eject\0" + "XF86Excel\0" + "XF86Explorer\0" + "XF86Favorites\0" + "XF86Finance\0" + "XF86Forward\0" + "XF86FrameBack\0" + "XF86FrameForward\0" + "XF86Game\0" + "XF86Go\0" + "XF86Green\0" + "XF86Hibernate\0" + "XF86History\0" + "XF86HomePage\0" + "XF86HotLinks\0" + "XF86iTouch\0" + "XF86KbdBrightnessDown\0" + "XF86KbdBrightnessUp\0" + "XF86KbdLightOnOff\0" + "XF86Launch0\0" + "XF86Launch1\0" + "XF86Launch2\0" + "XF86Launch3\0" + "XF86Launch4\0" + "XF86Launch5\0" + "XF86Launch6\0" + "XF86Launch7\0" + "XF86Launch8\0" + "XF86Launch9\0" + "XF86LaunchA\0" + "XF86LaunchB\0" + "XF86LaunchC\0" + "XF86LaunchD\0" + "XF86LaunchE\0" + "XF86LaunchF\0" + "XF86LightBulb\0" + "XF86LogGrabInfo\0" + "XF86LogOff\0" + "XF86LogWindowTree\0" + "XF86Mail\0" + "XF86MailForward\0" + "XF86Market\0" + "XF86Meeting\0" + "XF86Memo\0" + "XF86MenuKB\0" + "XF86MenuPB\0" + "XF86Messenger\0" + "XF86ModeLock\0" + "XF86MonBrightnessDown\0" + "XF86MonBrightnessUp\0" + "XF86Music\0" + "XF86MyComputer\0" + "XF86MySites\0" + "XF86New\0" + "XF86News\0" + "XF86Next_VMode\0" + "XF86OfficeHome\0" + "XF86Open\0" + "XF86OpenURL\0" + "XF86Option\0" + "XF86Paste\0" + "XF86Phone\0" + "XF86Pictures\0" + "XF86PowerDown\0" + "XF86PowerOff\0" + "XF86Prev_VMode\0" + "XF86Q\0" + "XF86Red\0" + "XF86Refresh\0" + "XF86Reload\0" + "XF86Reply\0" + "XF86RockerDown\0" + "XF86RockerEnter\0" + "XF86RockerUp\0" + "XF86RotateWindows\0" + "XF86RotationKB\0" + "XF86RotationPB\0" + "XF86Save\0" + "XF86ScreenSaver\0" + "XF86ScrollClick\0" + "XF86ScrollDown\0" + "XF86ScrollUp\0" + "XF86Search\0" + "XF86Select\0" + "XF86Send\0" + "XF86Shop\0" + "XF86Sleep\0" + "XF86Spell\0" + "XF86SplitScreen\0" + "XF86Standby\0" + "XF86Start\0" + "XF86Stop\0" + "XF86Subtitle\0" + "XF86Support\0" + "XF86Suspend\0" + "XF86Switch_VT_1\0" + "XF86Switch_VT_10\0" + "XF86Switch_VT_11\0" + "XF86Switch_VT_12\0" + "XF86Switch_VT_2\0" + "XF86Switch_VT_3\0" + "XF86Switch_VT_4\0" + "XF86Switch_VT_5\0" + "XF86Switch_VT_6\0" + "XF86Switch_VT_7\0" + "XF86Switch_VT_8\0" + "XF86Switch_VT_9\0" + "XF86TaskPane\0" + "XF86Terminal\0" + "XF86Time\0" + "XF86ToDoList\0" + "XF86Tools\0" + "XF86TopMenu\0" + "XF86TouchpadOff\0" + "XF86TouchpadOn\0" + "XF86TouchpadToggle\0" + "XF86Travel\0" + "XF86Ungrab\0" + "XF86User1KB\0" + "XF86User2KB\0" + "XF86UserPB\0" + "XF86UWB\0" + "XF86VendorHome\0" + "XF86Video\0" + "XF86View\0" + "XF86WakeUp\0" + "XF86WebCam\0" + "XF86WheelButton\0" + "XF86WLAN\0" + "XF86Word\0" + "XF86WWW\0" + "XF86Xfer\0" + "XF86Yellow\0" + "XF86ZoomIn\0" + "XF86ZoomOut\0" + "Y\0" + "y\0" + "Yacute\0" + "yacute\0" + "Ybelowdot\0" + "ybelowdot\0" + "Ycircumflex\0" + "ycircumflex\0" + "ydiaeresis\0" + "Ydiaeresis\0" + "yen\0" + "Ygrave\0" + "ygrave\0" + "Yhook\0" + "yhook\0" + "Ytilde\0" + "ytilde\0" + "Z\0" + "z\0" + "Zabovedot\0" + "zabovedot\0" + "Zacute\0" + "zacute\0" + "Zcaron\0" + "zcaron\0" + "Zen_Koho\0" + "Zenkaku\0" + "Zenkaku_Hankaku\0" + "zerosubscript\0" + "zerosuperior\0" + "Zstroke\0" + "zstroke\0" +; +#pragma GCC diagnostic pop struct name_keysym { - const char *name; xkb_keysym_t keysym; + uint32_t offset; }; static const struct name_keysym name_to_keysym[] = { - { "0", XKB_KEY_0 }, - { "1", XKB_KEY_1 }, - { "2", XKB_KEY_2 }, - { "3", XKB_KEY_3 }, - { "3270_AltCursor", XKB_KEY_3270_AltCursor }, - { "3270_Attn", XKB_KEY_3270_Attn }, - { "3270_BackTab", XKB_KEY_3270_BackTab }, - { "3270_ChangeScreen", XKB_KEY_3270_ChangeScreen }, - { "3270_Copy", XKB_KEY_3270_Copy }, - { "3270_CursorBlink", XKB_KEY_3270_CursorBlink }, - { "3270_CursorSelect", XKB_KEY_3270_CursorSelect }, - { "3270_DeleteWord", XKB_KEY_3270_DeleteWord }, - { "3270_Duplicate", XKB_KEY_3270_Duplicate }, - { "3270_Enter", XKB_KEY_3270_Enter }, - { "3270_EraseEOF", XKB_KEY_3270_EraseEOF }, - { "3270_EraseInput", XKB_KEY_3270_EraseInput }, - { "3270_ExSelect", XKB_KEY_3270_ExSelect }, - { "3270_FieldMark", XKB_KEY_3270_FieldMark }, - { "3270_Ident", XKB_KEY_3270_Ident }, - { "3270_Jump", XKB_KEY_3270_Jump }, - { "3270_KeyClick", XKB_KEY_3270_KeyClick }, - { "3270_Left2", XKB_KEY_3270_Left2 }, - { "3270_PA1", XKB_KEY_3270_PA1 }, - { "3270_PA2", XKB_KEY_3270_PA2 }, - { "3270_PA3", XKB_KEY_3270_PA3 }, - { "3270_Play", XKB_KEY_3270_Play }, - { "3270_PrintScreen", XKB_KEY_3270_PrintScreen }, - { "3270_Quit", XKB_KEY_3270_Quit }, - { "3270_Record", XKB_KEY_3270_Record }, - { "3270_Reset", XKB_KEY_3270_Reset }, - { "3270_Right2", XKB_KEY_3270_Right2 }, - { "3270_Rule", XKB_KEY_3270_Rule }, - { "3270_Setup", XKB_KEY_3270_Setup }, - { "3270_Test", XKB_KEY_3270_Test }, - { "4", XKB_KEY_4 }, - { "5", XKB_KEY_5 }, - { "6", XKB_KEY_6 }, - { "7", XKB_KEY_7 }, - { "8", XKB_KEY_8 }, - { "9", XKB_KEY_9 }, - { "A", XKB_KEY_A }, - { "a", XKB_KEY_a }, - { "Aacute", XKB_KEY_Aacute }, - { "aacute", XKB_KEY_aacute }, - { "Abelowdot", XKB_KEY_Abelowdot }, - { "abelowdot", XKB_KEY_abelowdot }, - { "abovedot", XKB_KEY_abovedot }, - { "Abreve", XKB_KEY_Abreve }, - { "abreve", XKB_KEY_abreve }, - { "Abreveacute", XKB_KEY_Abreveacute }, - { "abreveacute", XKB_KEY_abreveacute }, - { "Abrevebelowdot", XKB_KEY_Abrevebelowdot }, - { "abrevebelowdot", XKB_KEY_abrevebelowdot }, - { "Abrevegrave", XKB_KEY_Abrevegrave }, - { "abrevegrave", XKB_KEY_abrevegrave }, - { "Abrevehook", XKB_KEY_Abrevehook }, - { "abrevehook", XKB_KEY_abrevehook }, - { "Abrevetilde", XKB_KEY_Abrevetilde }, - { "abrevetilde", XKB_KEY_abrevetilde }, - { "AccessX_Enable", XKB_KEY_AccessX_Enable }, - { "AccessX_Feedback_Enable", XKB_KEY_AccessX_Feedback_Enable }, - { "Acircumflex", XKB_KEY_Acircumflex }, - { "acircumflex", XKB_KEY_acircumflex }, - { "Acircumflexacute", XKB_KEY_Acircumflexacute }, - { "acircumflexacute", XKB_KEY_acircumflexacute }, - { "Acircumflexbelowdot", XKB_KEY_Acircumflexbelowdot }, - { "acircumflexbelowdot", XKB_KEY_acircumflexbelowdot }, - { "Acircumflexgrave", XKB_KEY_Acircumflexgrave }, - { "acircumflexgrave", XKB_KEY_acircumflexgrave }, - { "Acircumflexhook", XKB_KEY_Acircumflexhook }, - { "acircumflexhook", XKB_KEY_acircumflexhook }, - { "Acircumflextilde", XKB_KEY_Acircumflextilde }, - { "acircumflextilde", XKB_KEY_acircumflextilde }, - { "acute", XKB_KEY_acute }, - { "Adiaeresis", XKB_KEY_Adiaeresis }, - { "adiaeresis", XKB_KEY_adiaeresis }, - { "AE", XKB_KEY_AE }, - { "ae", XKB_KEY_ae }, - { "Agrave", XKB_KEY_Agrave }, - { "agrave", XKB_KEY_agrave }, - { "Ahook", XKB_KEY_Ahook }, - { "ahook", XKB_KEY_ahook }, - { "Alt_L", XKB_KEY_Alt_L }, - { "Alt_R", XKB_KEY_Alt_R }, - { "Amacron", XKB_KEY_Amacron }, - { "amacron", XKB_KEY_amacron }, - { "ampersand", XKB_KEY_ampersand }, - { "Aogonek", XKB_KEY_Aogonek }, - { "aogonek", XKB_KEY_aogonek }, - { "apostrophe", XKB_KEY_apostrophe }, - { "approxeq", XKB_KEY_approxeq }, - { "approximate", XKB_KEY_approximate }, - { "Arabic_0", XKB_KEY_Arabic_0 }, - { "Arabic_1", XKB_KEY_Arabic_1 }, - { "Arabic_2", XKB_KEY_Arabic_2 }, - { "Arabic_3", XKB_KEY_Arabic_3 }, - { "Arabic_4", XKB_KEY_Arabic_4 }, - { "Arabic_5", XKB_KEY_Arabic_5 }, - { "Arabic_6", XKB_KEY_Arabic_6 }, - { "Arabic_7", XKB_KEY_Arabic_7 }, - { "Arabic_8", XKB_KEY_Arabic_8 }, - { "Arabic_9", XKB_KEY_Arabic_9 }, - { "Arabic_ain", XKB_KEY_Arabic_ain }, - { "Arabic_alef", XKB_KEY_Arabic_alef }, - { "Arabic_alefmaksura", XKB_KEY_Arabic_alefmaksura }, - { "Arabic_beh", XKB_KEY_Arabic_beh }, - { "Arabic_comma", XKB_KEY_Arabic_comma }, - { "Arabic_dad", XKB_KEY_Arabic_dad }, - { "Arabic_dal", XKB_KEY_Arabic_dal }, - { "Arabic_damma", XKB_KEY_Arabic_damma }, - { "Arabic_dammatan", XKB_KEY_Arabic_dammatan }, - { "Arabic_ddal", XKB_KEY_Arabic_ddal }, - { "Arabic_farsi_yeh", XKB_KEY_Arabic_farsi_yeh }, - { "Arabic_fatha", XKB_KEY_Arabic_fatha }, - { "Arabic_fathatan", XKB_KEY_Arabic_fathatan }, - { "Arabic_feh", XKB_KEY_Arabic_feh }, - { "Arabic_fullstop", XKB_KEY_Arabic_fullstop }, - { "Arabic_gaf", XKB_KEY_Arabic_gaf }, - { "Arabic_ghain", XKB_KEY_Arabic_ghain }, - { "Arabic_ha", XKB_KEY_Arabic_ha }, - { "Arabic_hah", XKB_KEY_Arabic_hah }, - { "Arabic_hamza", XKB_KEY_Arabic_hamza }, - { "Arabic_hamza_above", XKB_KEY_Arabic_hamza_above }, - { "Arabic_hamza_below", XKB_KEY_Arabic_hamza_below }, - { "Arabic_hamzaonalef", XKB_KEY_Arabic_hamzaonalef }, - { "Arabic_hamzaonwaw", XKB_KEY_Arabic_hamzaonwaw }, - { "Arabic_hamzaonyeh", XKB_KEY_Arabic_hamzaonyeh }, - { "Arabic_hamzaunderalef", XKB_KEY_Arabic_hamzaunderalef }, - { "Arabic_heh", XKB_KEY_Arabic_heh }, - { "Arabic_heh_doachashmee", XKB_KEY_Arabic_heh_doachashmee }, - { "Arabic_heh_goal", XKB_KEY_Arabic_heh_goal }, - { "Arabic_jeem", XKB_KEY_Arabic_jeem }, - { "Arabic_jeh", XKB_KEY_Arabic_jeh }, - { "Arabic_kaf", XKB_KEY_Arabic_kaf }, - { "Arabic_kasra", XKB_KEY_Arabic_kasra }, - { "Arabic_kasratan", XKB_KEY_Arabic_kasratan }, - { "Arabic_keheh", XKB_KEY_Arabic_keheh }, - { "Arabic_khah", XKB_KEY_Arabic_khah }, - { "Arabic_lam", XKB_KEY_Arabic_lam }, - { "Arabic_madda_above", XKB_KEY_Arabic_madda_above }, - { "Arabic_maddaonalef", XKB_KEY_Arabic_maddaonalef }, - { "Arabic_meem", XKB_KEY_Arabic_meem }, - { "Arabic_noon", XKB_KEY_Arabic_noon }, - { "Arabic_noon_ghunna", XKB_KEY_Arabic_noon_ghunna }, - { "Arabic_peh", XKB_KEY_Arabic_peh }, - { "Arabic_percent", XKB_KEY_Arabic_percent }, - { "Arabic_qaf", XKB_KEY_Arabic_qaf }, - { "Arabic_question_mark", XKB_KEY_Arabic_question_mark }, - { "Arabic_ra", XKB_KEY_Arabic_ra }, - { "Arabic_rreh", XKB_KEY_Arabic_rreh }, - { "Arabic_sad", XKB_KEY_Arabic_sad }, - { "Arabic_seen", XKB_KEY_Arabic_seen }, - { "Arabic_semicolon", XKB_KEY_Arabic_semicolon }, - { "Arabic_shadda", XKB_KEY_Arabic_shadda }, - { "Arabic_sheen", XKB_KEY_Arabic_sheen }, - { "Arabic_sukun", XKB_KEY_Arabic_sukun }, - { "Arabic_superscript_alef", XKB_KEY_Arabic_superscript_alef }, - { "Arabic_switch", XKB_KEY_Arabic_switch }, - { "Arabic_tah", XKB_KEY_Arabic_tah }, - { "Arabic_tatweel", XKB_KEY_Arabic_tatweel }, - { "Arabic_tcheh", XKB_KEY_Arabic_tcheh }, - { "Arabic_teh", XKB_KEY_Arabic_teh }, - { "Arabic_tehmarbuta", XKB_KEY_Arabic_tehmarbuta }, - { "Arabic_thal", XKB_KEY_Arabic_thal }, - { "Arabic_theh", XKB_KEY_Arabic_theh }, - { "Arabic_tteh", XKB_KEY_Arabic_tteh }, - { "Arabic_veh", XKB_KEY_Arabic_veh }, - { "Arabic_waw", XKB_KEY_Arabic_waw }, - { "Arabic_yeh", XKB_KEY_Arabic_yeh }, - { "Arabic_yeh_baree", XKB_KEY_Arabic_yeh_baree }, - { "Arabic_zah", XKB_KEY_Arabic_zah }, - { "Arabic_zain", XKB_KEY_Arabic_zain }, - { "Aring", XKB_KEY_Aring }, - { "aring", XKB_KEY_aring }, - { "Armenian_accent", XKB_KEY_Armenian_accent }, - { "Armenian_amanak", XKB_KEY_Armenian_amanak }, - { "Armenian_apostrophe", XKB_KEY_Armenian_apostrophe }, - { "Armenian_AT", XKB_KEY_Armenian_AT }, - { "Armenian_at", XKB_KEY_Armenian_at }, - { "Armenian_AYB", XKB_KEY_Armenian_AYB }, - { "Armenian_ayb", XKB_KEY_Armenian_ayb }, - { "Armenian_BEN", XKB_KEY_Armenian_BEN }, - { "Armenian_ben", XKB_KEY_Armenian_ben }, - { "Armenian_but", XKB_KEY_Armenian_but }, - { "Armenian_CHA", XKB_KEY_Armenian_CHA }, - { "Armenian_cha", XKB_KEY_Armenian_cha }, - { "Armenian_DA", XKB_KEY_Armenian_DA }, - { "Armenian_da", XKB_KEY_Armenian_da }, - { "Armenian_DZA", XKB_KEY_Armenian_DZA }, - { "Armenian_dza", XKB_KEY_Armenian_dza }, - { "Armenian_E", XKB_KEY_Armenian_E }, - { "Armenian_e", XKB_KEY_Armenian_e }, - { "Armenian_exclam", XKB_KEY_Armenian_exclam }, - { "Armenian_FE", XKB_KEY_Armenian_FE }, - { "Armenian_fe", XKB_KEY_Armenian_fe }, - { "Armenian_full_stop", XKB_KEY_Armenian_full_stop }, - { "Armenian_GHAT", XKB_KEY_Armenian_GHAT }, - { "Armenian_ghat", XKB_KEY_Armenian_ghat }, - { "Armenian_GIM", XKB_KEY_Armenian_GIM }, - { "Armenian_gim", XKB_KEY_Armenian_gim }, - { "Armenian_HI", XKB_KEY_Armenian_HI }, - { "Armenian_hi", XKB_KEY_Armenian_hi }, - { "Armenian_HO", XKB_KEY_Armenian_HO }, - { "Armenian_ho", XKB_KEY_Armenian_ho }, - { "Armenian_hyphen", XKB_KEY_Armenian_hyphen }, - { "Armenian_INI", XKB_KEY_Armenian_INI }, - { "Armenian_ini", XKB_KEY_Armenian_ini }, - { "Armenian_JE", XKB_KEY_Armenian_JE }, - { "Armenian_je", XKB_KEY_Armenian_je }, - { "Armenian_KE", XKB_KEY_Armenian_KE }, - { "Armenian_ke", XKB_KEY_Armenian_ke }, - { "Armenian_KEN", XKB_KEY_Armenian_KEN }, - { "Armenian_ken", XKB_KEY_Armenian_ken }, - { "Armenian_KHE", XKB_KEY_Armenian_KHE }, - { "Armenian_khe", XKB_KEY_Armenian_khe }, - { "Armenian_ligature_ew", XKB_KEY_Armenian_ligature_ew }, - { "Armenian_LYUN", XKB_KEY_Armenian_LYUN }, - { "Armenian_lyun", XKB_KEY_Armenian_lyun }, - { "Armenian_MEN", XKB_KEY_Armenian_MEN }, - { "Armenian_men", XKB_KEY_Armenian_men }, - { "Armenian_NU", XKB_KEY_Armenian_NU }, - { "Armenian_nu", XKB_KEY_Armenian_nu }, - { "Armenian_O", XKB_KEY_Armenian_O }, - { "Armenian_o", XKB_KEY_Armenian_o }, - { "Armenian_paruyk", XKB_KEY_Armenian_paruyk }, - { "Armenian_PE", XKB_KEY_Armenian_PE }, - { "Armenian_pe", XKB_KEY_Armenian_pe }, - { "Armenian_PYUR", XKB_KEY_Armenian_PYUR }, - { "Armenian_pyur", XKB_KEY_Armenian_pyur }, - { "Armenian_question", XKB_KEY_Armenian_question }, - { "Armenian_RA", XKB_KEY_Armenian_RA }, - { "Armenian_ra", XKB_KEY_Armenian_ra }, - { "Armenian_RE", XKB_KEY_Armenian_RE }, - { "Armenian_re", XKB_KEY_Armenian_re }, - { "Armenian_SE", XKB_KEY_Armenian_SE }, - { "Armenian_se", XKB_KEY_Armenian_se }, - { "Armenian_separation_mark", XKB_KEY_Armenian_separation_mark }, - { "Armenian_SHA", XKB_KEY_Armenian_SHA }, - { "Armenian_sha", XKB_KEY_Armenian_sha }, - { "Armenian_shesht", XKB_KEY_Armenian_shesht }, - { "Armenian_TCHE", XKB_KEY_Armenian_TCHE }, - { "Armenian_tche", XKB_KEY_Armenian_tche }, - { "Armenian_TO", XKB_KEY_Armenian_TO }, - { "Armenian_to", XKB_KEY_Armenian_to }, - { "Armenian_TSA", XKB_KEY_Armenian_TSA }, - { "Armenian_tsa", XKB_KEY_Armenian_tsa }, - { "Armenian_TSO", XKB_KEY_Armenian_TSO }, - { "Armenian_tso", XKB_KEY_Armenian_tso }, - { "Armenian_TYUN", XKB_KEY_Armenian_TYUN }, - { "Armenian_tyun", XKB_KEY_Armenian_tyun }, - { "Armenian_verjaket", XKB_KEY_Armenian_verjaket }, - { "Armenian_VEV", XKB_KEY_Armenian_VEV }, - { "Armenian_vev", XKB_KEY_Armenian_vev }, - { "Armenian_VO", XKB_KEY_Armenian_VO }, - { "Armenian_vo", XKB_KEY_Armenian_vo }, - { "Armenian_VYUN", XKB_KEY_Armenian_VYUN }, - { "Armenian_vyun", XKB_KEY_Armenian_vyun }, - { "Armenian_YECH", XKB_KEY_Armenian_YECH }, - { "Armenian_yech", XKB_KEY_Armenian_yech }, - { "Armenian_yentamna", XKB_KEY_Armenian_yentamna }, - { "Armenian_ZA", XKB_KEY_Armenian_ZA }, - { "Armenian_za", XKB_KEY_Armenian_za }, - { "Armenian_ZHE", XKB_KEY_Armenian_ZHE }, - { "Armenian_zhe", XKB_KEY_Armenian_zhe }, - { "asciicircum", XKB_KEY_asciicircum }, - { "asciitilde", XKB_KEY_asciitilde }, - { "asterisk", XKB_KEY_asterisk }, - { "at", XKB_KEY_at }, - { "Atilde", XKB_KEY_Atilde }, - { "atilde", XKB_KEY_atilde }, - { "AudibleBell_Enable", XKB_KEY_AudibleBell_Enable }, - { "B", XKB_KEY_B }, - { "b", XKB_KEY_b }, - { "Babovedot", XKB_KEY_Babovedot }, - { "babovedot", XKB_KEY_babovedot }, - { "backslash", XKB_KEY_backslash }, - { "BackSpace", XKB_KEY_BackSpace }, - { "BackTab", XKB_KEY_BackTab }, - { "ballotcross", XKB_KEY_ballotcross }, - { "bar", XKB_KEY_bar }, - { "because", XKB_KEY_because }, - { "Begin", XKB_KEY_Begin }, - { "blank", XKB_KEY_blank }, - { "block", XKB_KEY_block }, - { "botintegral", XKB_KEY_botintegral }, - { "botleftparens", XKB_KEY_botleftparens }, - { "botleftsqbracket", XKB_KEY_botleftsqbracket }, - { "botleftsummation", XKB_KEY_botleftsummation }, - { "botrightparens", XKB_KEY_botrightparens }, - { "botrightsqbracket", XKB_KEY_botrightsqbracket }, - { "botrightsummation", XKB_KEY_botrightsummation }, - { "bott", XKB_KEY_bott }, - { "botvertsummationconnector", XKB_KEY_botvertsummationconnector }, - { "BounceKeys_Enable", XKB_KEY_BounceKeys_Enable }, - { "braceleft", XKB_KEY_braceleft }, - { "braceright", XKB_KEY_braceright }, - { "bracketleft", XKB_KEY_bracketleft }, - { "bracketright", XKB_KEY_bracketright }, - { "braille_blank", XKB_KEY_braille_blank }, - { "braille_dot_1", XKB_KEY_braille_dot_1 }, - { "braille_dot_10", XKB_KEY_braille_dot_10 }, - { "braille_dot_2", XKB_KEY_braille_dot_2 }, - { "braille_dot_3", XKB_KEY_braille_dot_3 }, - { "braille_dot_4", XKB_KEY_braille_dot_4 }, - { "braille_dot_5", XKB_KEY_braille_dot_5 }, - { "braille_dot_6", XKB_KEY_braille_dot_6 }, - { "braille_dot_7", XKB_KEY_braille_dot_7 }, - { "braille_dot_8", XKB_KEY_braille_dot_8 }, - { "braille_dot_9", XKB_KEY_braille_dot_9 }, - { "braille_dots_1", XKB_KEY_braille_dots_1 }, - { "braille_dots_12", XKB_KEY_braille_dots_12 }, - { "braille_dots_123", XKB_KEY_braille_dots_123 }, - { "braille_dots_1234", XKB_KEY_braille_dots_1234 }, - { "braille_dots_12345", XKB_KEY_braille_dots_12345 }, - { "braille_dots_123456", XKB_KEY_braille_dots_123456 }, - { "braille_dots_1234567", XKB_KEY_braille_dots_1234567 }, - { "braille_dots_12345678", XKB_KEY_braille_dots_12345678 }, - { "braille_dots_1234568", XKB_KEY_braille_dots_1234568 }, - { "braille_dots_123457", XKB_KEY_braille_dots_123457 }, - { "braille_dots_1234578", XKB_KEY_braille_dots_1234578 }, - { "braille_dots_123458", XKB_KEY_braille_dots_123458 }, - { "braille_dots_12346", XKB_KEY_braille_dots_12346 }, - { "braille_dots_123467", XKB_KEY_braille_dots_123467 }, - { "braille_dots_1234678", XKB_KEY_braille_dots_1234678 }, - { "braille_dots_123468", XKB_KEY_braille_dots_123468 }, - { "braille_dots_12347", XKB_KEY_braille_dots_12347 }, - { "braille_dots_123478", XKB_KEY_braille_dots_123478 }, - { "braille_dots_12348", XKB_KEY_braille_dots_12348 }, - { "braille_dots_1235", XKB_KEY_braille_dots_1235 }, - { "braille_dots_12356", XKB_KEY_braille_dots_12356 }, - { "braille_dots_123567", XKB_KEY_braille_dots_123567 }, - { "braille_dots_1235678", XKB_KEY_braille_dots_1235678 }, - { "braille_dots_123568", XKB_KEY_braille_dots_123568 }, - { "braille_dots_12357", XKB_KEY_braille_dots_12357 }, - { "braille_dots_123578", XKB_KEY_braille_dots_123578 }, - { "braille_dots_12358", XKB_KEY_braille_dots_12358 }, - { "braille_dots_1236", XKB_KEY_braille_dots_1236 }, - { "braille_dots_12367", XKB_KEY_braille_dots_12367 }, - { "braille_dots_123678", XKB_KEY_braille_dots_123678 }, - { "braille_dots_12368", XKB_KEY_braille_dots_12368 }, - { "braille_dots_1237", XKB_KEY_braille_dots_1237 }, - { "braille_dots_12378", XKB_KEY_braille_dots_12378 }, - { "braille_dots_1238", XKB_KEY_braille_dots_1238 }, - { "braille_dots_124", XKB_KEY_braille_dots_124 }, - { "braille_dots_1245", XKB_KEY_braille_dots_1245 }, - { "braille_dots_12456", XKB_KEY_braille_dots_12456 }, - { "braille_dots_124567", XKB_KEY_braille_dots_124567 }, - { "braille_dots_1245678", XKB_KEY_braille_dots_1245678 }, - { "braille_dots_124568", XKB_KEY_braille_dots_124568 }, - { "braille_dots_12457", XKB_KEY_braille_dots_12457 }, - { "braille_dots_124578", XKB_KEY_braille_dots_124578 }, - { "braille_dots_12458", XKB_KEY_braille_dots_12458 }, - { "braille_dots_1246", XKB_KEY_braille_dots_1246 }, - { "braille_dots_12467", XKB_KEY_braille_dots_12467 }, - { "braille_dots_124678", XKB_KEY_braille_dots_124678 }, - { "braille_dots_12468", XKB_KEY_braille_dots_12468 }, - { "braille_dots_1247", XKB_KEY_braille_dots_1247 }, - { "braille_dots_12478", XKB_KEY_braille_dots_12478 }, - { "braille_dots_1248", XKB_KEY_braille_dots_1248 }, - { "braille_dots_125", XKB_KEY_braille_dots_125 }, - { "braille_dots_1256", XKB_KEY_braille_dots_1256 }, - { "braille_dots_12567", XKB_KEY_braille_dots_12567 }, - { "braille_dots_125678", XKB_KEY_braille_dots_125678 }, - { "braille_dots_12568", XKB_KEY_braille_dots_12568 }, - { "braille_dots_1257", XKB_KEY_braille_dots_1257 }, - { "braille_dots_12578", XKB_KEY_braille_dots_12578 }, - { "braille_dots_1258", XKB_KEY_braille_dots_1258 }, - { "braille_dots_126", XKB_KEY_braille_dots_126 }, - { "braille_dots_1267", XKB_KEY_braille_dots_1267 }, - { "braille_dots_12678", XKB_KEY_braille_dots_12678 }, - { "braille_dots_1268", XKB_KEY_braille_dots_1268 }, - { "braille_dots_127", XKB_KEY_braille_dots_127 }, - { "braille_dots_1278", XKB_KEY_braille_dots_1278 }, - { "braille_dots_128", XKB_KEY_braille_dots_128 }, - { "braille_dots_13", XKB_KEY_braille_dots_13 }, - { "braille_dots_134", XKB_KEY_braille_dots_134 }, - { "braille_dots_1345", XKB_KEY_braille_dots_1345 }, - { "braille_dots_13456", XKB_KEY_braille_dots_13456 }, - { "braille_dots_134567", XKB_KEY_braille_dots_134567 }, - { "braille_dots_1345678", XKB_KEY_braille_dots_1345678 }, - { "braille_dots_134568", XKB_KEY_braille_dots_134568 }, - { "braille_dots_13457", XKB_KEY_braille_dots_13457 }, - { "braille_dots_134578", XKB_KEY_braille_dots_134578 }, - { "braille_dots_13458", XKB_KEY_braille_dots_13458 }, - { "braille_dots_1346", XKB_KEY_braille_dots_1346 }, - { "braille_dots_13467", XKB_KEY_braille_dots_13467 }, - { "braille_dots_134678", XKB_KEY_braille_dots_134678 }, - { "braille_dots_13468", XKB_KEY_braille_dots_13468 }, - { "braille_dots_1347", XKB_KEY_braille_dots_1347 }, - { "braille_dots_13478", XKB_KEY_braille_dots_13478 }, - { "braille_dots_1348", XKB_KEY_braille_dots_1348 }, - { "braille_dots_135", XKB_KEY_braille_dots_135 }, - { "braille_dots_1356", XKB_KEY_braille_dots_1356 }, - { "braille_dots_13567", XKB_KEY_braille_dots_13567 }, - { "braille_dots_135678", XKB_KEY_braille_dots_135678 }, - { "braille_dots_13568", XKB_KEY_braille_dots_13568 }, - { "braille_dots_1357", XKB_KEY_braille_dots_1357 }, - { "braille_dots_13578", XKB_KEY_braille_dots_13578 }, - { "braille_dots_1358", XKB_KEY_braille_dots_1358 }, - { "braille_dots_136", XKB_KEY_braille_dots_136 }, - { "braille_dots_1367", XKB_KEY_braille_dots_1367 }, - { "braille_dots_13678", XKB_KEY_braille_dots_13678 }, - { "braille_dots_1368", XKB_KEY_braille_dots_1368 }, - { "braille_dots_137", XKB_KEY_braille_dots_137 }, - { "braille_dots_1378", XKB_KEY_braille_dots_1378 }, - { "braille_dots_138", XKB_KEY_braille_dots_138 }, - { "braille_dots_14", XKB_KEY_braille_dots_14 }, - { "braille_dots_145", XKB_KEY_braille_dots_145 }, - { "braille_dots_1456", XKB_KEY_braille_dots_1456 }, - { "braille_dots_14567", XKB_KEY_braille_dots_14567 }, - { "braille_dots_145678", XKB_KEY_braille_dots_145678 }, - { "braille_dots_14568", XKB_KEY_braille_dots_14568 }, - { "braille_dots_1457", XKB_KEY_braille_dots_1457 }, - { "braille_dots_14578", XKB_KEY_braille_dots_14578 }, - { "braille_dots_1458", XKB_KEY_braille_dots_1458 }, - { "braille_dots_146", XKB_KEY_braille_dots_146 }, - { "braille_dots_1467", XKB_KEY_braille_dots_1467 }, - { "braille_dots_14678", XKB_KEY_braille_dots_14678 }, - { "braille_dots_1468", XKB_KEY_braille_dots_1468 }, - { "braille_dots_147", XKB_KEY_braille_dots_147 }, - { "braille_dots_1478", XKB_KEY_braille_dots_1478 }, - { "braille_dots_148", XKB_KEY_braille_dots_148 }, - { "braille_dots_15", XKB_KEY_braille_dots_15 }, - { "braille_dots_156", XKB_KEY_braille_dots_156 }, - { "braille_dots_1567", XKB_KEY_braille_dots_1567 }, - { "braille_dots_15678", XKB_KEY_braille_dots_15678 }, - { "braille_dots_1568", XKB_KEY_braille_dots_1568 }, - { "braille_dots_157", XKB_KEY_braille_dots_157 }, - { "braille_dots_1578", XKB_KEY_braille_dots_1578 }, - { "braille_dots_158", XKB_KEY_braille_dots_158 }, - { "braille_dots_16", XKB_KEY_braille_dots_16 }, - { "braille_dots_167", XKB_KEY_braille_dots_167 }, - { "braille_dots_1678", XKB_KEY_braille_dots_1678 }, - { "braille_dots_168", XKB_KEY_braille_dots_168 }, - { "braille_dots_17", XKB_KEY_braille_dots_17 }, - { "braille_dots_178", XKB_KEY_braille_dots_178 }, - { "braille_dots_18", XKB_KEY_braille_dots_18 }, - { "braille_dots_2", XKB_KEY_braille_dots_2 }, - { "braille_dots_23", XKB_KEY_braille_dots_23 }, - { "braille_dots_234", XKB_KEY_braille_dots_234 }, - { "braille_dots_2345", XKB_KEY_braille_dots_2345 }, - { "braille_dots_23456", XKB_KEY_braille_dots_23456 }, - { "braille_dots_234567", XKB_KEY_braille_dots_234567 }, - { "braille_dots_2345678", XKB_KEY_braille_dots_2345678 }, - { "braille_dots_234568", XKB_KEY_braille_dots_234568 }, - { "braille_dots_23457", XKB_KEY_braille_dots_23457 }, - { "braille_dots_234578", XKB_KEY_braille_dots_234578 }, - { "braille_dots_23458", XKB_KEY_braille_dots_23458 }, - { "braille_dots_2346", XKB_KEY_braille_dots_2346 }, - { "braille_dots_23467", XKB_KEY_braille_dots_23467 }, - { "braille_dots_234678", XKB_KEY_braille_dots_234678 }, - { "braille_dots_23468", XKB_KEY_braille_dots_23468 }, - { "braille_dots_2347", XKB_KEY_braille_dots_2347 }, - { "braille_dots_23478", XKB_KEY_braille_dots_23478 }, - { "braille_dots_2348", XKB_KEY_braille_dots_2348 }, - { "braille_dots_235", XKB_KEY_braille_dots_235 }, - { "braille_dots_2356", XKB_KEY_braille_dots_2356 }, - { "braille_dots_23567", XKB_KEY_braille_dots_23567 }, - { "braille_dots_235678", XKB_KEY_braille_dots_235678 }, - { "braille_dots_23568", XKB_KEY_braille_dots_23568 }, - { "braille_dots_2357", XKB_KEY_braille_dots_2357 }, - { "braille_dots_23578", XKB_KEY_braille_dots_23578 }, - { "braille_dots_2358", XKB_KEY_braille_dots_2358 }, - { "braille_dots_236", XKB_KEY_braille_dots_236 }, - { "braille_dots_2367", XKB_KEY_braille_dots_2367 }, - { "braille_dots_23678", XKB_KEY_braille_dots_23678 }, - { "braille_dots_2368", XKB_KEY_braille_dots_2368 }, - { "braille_dots_237", XKB_KEY_braille_dots_237 }, - { "braille_dots_2378", XKB_KEY_braille_dots_2378 }, - { "braille_dots_238", XKB_KEY_braille_dots_238 }, - { "braille_dots_24", XKB_KEY_braille_dots_24 }, - { "braille_dots_245", XKB_KEY_braille_dots_245 }, - { "braille_dots_2456", XKB_KEY_braille_dots_2456 }, - { "braille_dots_24567", XKB_KEY_braille_dots_24567 }, - { "braille_dots_245678", XKB_KEY_braille_dots_245678 }, - { "braille_dots_24568", XKB_KEY_braille_dots_24568 }, - { "braille_dots_2457", XKB_KEY_braille_dots_2457 }, - { "braille_dots_24578", XKB_KEY_braille_dots_24578 }, - { "braille_dots_2458", XKB_KEY_braille_dots_2458 }, - { "braille_dots_246", XKB_KEY_braille_dots_246 }, - { "braille_dots_2467", XKB_KEY_braille_dots_2467 }, - { "braille_dots_24678", XKB_KEY_braille_dots_24678 }, - { "braille_dots_2468", XKB_KEY_braille_dots_2468 }, - { "braille_dots_247", XKB_KEY_braille_dots_247 }, - { "braille_dots_2478", XKB_KEY_braille_dots_2478 }, - { "braille_dots_248", XKB_KEY_braille_dots_248 }, - { "braille_dots_25", XKB_KEY_braille_dots_25 }, - { "braille_dots_256", XKB_KEY_braille_dots_256 }, - { "braille_dots_2567", XKB_KEY_braille_dots_2567 }, - { "braille_dots_25678", XKB_KEY_braille_dots_25678 }, - { "braille_dots_2568", XKB_KEY_braille_dots_2568 }, - { "braille_dots_257", XKB_KEY_braille_dots_257 }, - { "braille_dots_2578", XKB_KEY_braille_dots_2578 }, - { "braille_dots_258", XKB_KEY_braille_dots_258 }, - { "braille_dots_26", XKB_KEY_braille_dots_26 }, - { "braille_dots_267", XKB_KEY_braille_dots_267 }, - { "braille_dots_2678", XKB_KEY_braille_dots_2678 }, - { "braille_dots_268", XKB_KEY_braille_dots_268 }, - { "braille_dots_27", XKB_KEY_braille_dots_27 }, - { "braille_dots_278", XKB_KEY_braille_dots_278 }, - { "braille_dots_28", XKB_KEY_braille_dots_28 }, - { "braille_dots_3", XKB_KEY_braille_dots_3 }, - { "braille_dots_34", XKB_KEY_braille_dots_34 }, - { "braille_dots_345", XKB_KEY_braille_dots_345 }, - { "braille_dots_3456", XKB_KEY_braille_dots_3456 }, - { "braille_dots_34567", XKB_KEY_braille_dots_34567 }, - { "braille_dots_345678", XKB_KEY_braille_dots_345678 }, - { "braille_dots_34568", XKB_KEY_braille_dots_34568 }, - { "braille_dots_3457", XKB_KEY_braille_dots_3457 }, - { "braille_dots_34578", XKB_KEY_braille_dots_34578 }, - { "braille_dots_3458", XKB_KEY_braille_dots_3458 }, - { "braille_dots_346", XKB_KEY_braille_dots_346 }, - { "braille_dots_3467", XKB_KEY_braille_dots_3467 }, - { "braille_dots_34678", XKB_KEY_braille_dots_34678 }, - { "braille_dots_3468", XKB_KEY_braille_dots_3468 }, - { "braille_dots_347", XKB_KEY_braille_dots_347 }, - { "braille_dots_3478", XKB_KEY_braille_dots_3478 }, - { "braille_dots_348", XKB_KEY_braille_dots_348 }, - { "braille_dots_35", XKB_KEY_braille_dots_35 }, - { "braille_dots_356", XKB_KEY_braille_dots_356 }, - { "braille_dots_3567", XKB_KEY_braille_dots_3567 }, - { "braille_dots_35678", XKB_KEY_braille_dots_35678 }, - { "braille_dots_3568", XKB_KEY_braille_dots_3568 }, - { "braille_dots_357", XKB_KEY_braille_dots_357 }, - { "braille_dots_3578", XKB_KEY_braille_dots_3578 }, - { "braille_dots_358", XKB_KEY_braille_dots_358 }, - { "braille_dots_36", XKB_KEY_braille_dots_36 }, - { "braille_dots_367", XKB_KEY_braille_dots_367 }, - { "braille_dots_3678", XKB_KEY_braille_dots_3678 }, - { "braille_dots_368", XKB_KEY_braille_dots_368 }, - { "braille_dots_37", XKB_KEY_braille_dots_37 }, - { "braille_dots_378", XKB_KEY_braille_dots_378 }, - { "braille_dots_38", XKB_KEY_braille_dots_38 }, - { "braille_dots_4", XKB_KEY_braille_dots_4 }, - { "braille_dots_45", XKB_KEY_braille_dots_45 }, - { "braille_dots_456", XKB_KEY_braille_dots_456 }, - { "braille_dots_4567", XKB_KEY_braille_dots_4567 }, - { "braille_dots_45678", XKB_KEY_braille_dots_45678 }, - { "braille_dots_4568", XKB_KEY_braille_dots_4568 }, - { "braille_dots_457", XKB_KEY_braille_dots_457 }, - { "braille_dots_4578", XKB_KEY_braille_dots_4578 }, - { "braille_dots_458", XKB_KEY_braille_dots_458 }, - { "braille_dots_46", XKB_KEY_braille_dots_46 }, - { "braille_dots_467", XKB_KEY_braille_dots_467 }, - { "braille_dots_4678", XKB_KEY_braille_dots_4678 }, - { "braille_dots_468", XKB_KEY_braille_dots_468 }, - { "braille_dots_47", XKB_KEY_braille_dots_47 }, - { "braille_dots_478", XKB_KEY_braille_dots_478 }, - { "braille_dots_48", XKB_KEY_braille_dots_48 }, - { "braille_dots_5", XKB_KEY_braille_dots_5 }, - { "braille_dots_56", XKB_KEY_braille_dots_56 }, - { "braille_dots_567", XKB_KEY_braille_dots_567 }, - { "braille_dots_5678", XKB_KEY_braille_dots_5678 }, - { "braille_dots_568", XKB_KEY_braille_dots_568 }, - { "braille_dots_57", XKB_KEY_braille_dots_57 }, - { "braille_dots_578", XKB_KEY_braille_dots_578 }, - { "braille_dots_58", XKB_KEY_braille_dots_58 }, - { "braille_dots_6", XKB_KEY_braille_dots_6 }, - { "braille_dots_67", XKB_KEY_braille_dots_67 }, - { "braille_dots_678", XKB_KEY_braille_dots_678 }, - { "braille_dots_68", XKB_KEY_braille_dots_68 }, - { "braille_dots_7", XKB_KEY_braille_dots_7 }, - { "braille_dots_78", XKB_KEY_braille_dots_78 }, - { "braille_dots_8", XKB_KEY_braille_dots_8 }, - { "Break", XKB_KEY_Break }, - { "breve", XKB_KEY_breve }, - { "brokenbar", XKB_KEY_brokenbar }, - { "Byelorussian_shortu", XKB_KEY_Byelorussian_shortu }, - { "Byelorussian_SHORTU", XKB_KEY_Byelorussian_SHORTU }, - { "C", XKB_KEY_C }, - { "c", XKB_KEY_c }, - { "c_h", XKB_KEY_c_h }, - { "C_h", XKB_KEY_C_h }, - { "C_H", XKB_KEY_C_H }, - { "Cabovedot", XKB_KEY_Cabovedot }, - { "cabovedot", XKB_KEY_cabovedot }, - { "Cacute", XKB_KEY_Cacute }, - { "cacute", XKB_KEY_cacute }, - { "Cancel", XKB_KEY_Cancel }, - { "Caps_Lock", XKB_KEY_Caps_Lock }, - { "careof", XKB_KEY_careof }, - { "caret", XKB_KEY_caret }, - { "caron", XKB_KEY_caron }, - { "Ccaron", XKB_KEY_Ccaron }, - { "ccaron", XKB_KEY_ccaron }, - { "Ccedilla", XKB_KEY_Ccedilla }, - { "ccedilla", XKB_KEY_ccedilla }, - { "Ccircumflex", XKB_KEY_Ccircumflex }, - { "ccircumflex", XKB_KEY_ccircumflex }, - { "cedilla", XKB_KEY_cedilla }, - { "cent", XKB_KEY_cent }, - { "ch", XKB_KEY_ch }, - { "Ch", XKB_KEY_Ch }, - { "CH", XKB_KEY_CH }, - { "checkerboard", XKB_KEY_checkerboard }, - { "checkmark", XKB_KEY_checkmark }, - { "circle", XKB_KEY_circle }, - { "Clear", XKB_KEY_Clear }, - { "ClearLine", XKB_KEY_ClearLine }, - { "club", XKB_KEY_club }, - { "Codeinput", XKB_KEY_Codeinput }, - { "colon", XKB_KEY_colon }, - { "ColonSign", XKB_KEY_ColonSign }, - { "comma", XKB_KEY_comma }, - { "containsas", XKB_KEY_containsas }, - { "Control_L", XKB_KEY_Control_L }, - { "Control_R", XKB_KEY_Control_R }, - { "copyright", XKB_KEY_copyright }, - { "cr", XKB_KEY_cr }, - { "crossinglines", XKB_KEY_crossinglines }, - { "CruzeiroSign", XKB_KEY_CruzeiroSign }, - { "cuberoot", XKB_KEY_cuberoot }, - { "currency", XKB_KEY_currency }, - { "cursor", XKB_KEY_cursor }, - { "Cyrillic_a", XKB_KEY_Cyrillic_a }, - { "Cyrillic_A", XKB_KEY_Cyrillic_A }, - { "Cyrillic_be", XKB_KEY_Cyrillic_be }, - { "Cyrillic_BE", XKB_KEY_Cyrillic_BE }, - { "Cyrillic_che", XKB_KEY_Cyrillic_che }, - { "Cyrillic_CHE", XKB_KEY_Cyrillic_CHE }, - { "Cyrillic_CHE_descender", XKB_KEY_Cyrillic_CHE_descender }, - { "Cyrillic_che_descender", XKB_KEY_Cyrillic_che_descender }, - { "Cyrillic_CHE_vertstroke", XKB_KEY_Cyrillic_CHE_vertstroke }, - { "Cyrillic_che_vertstroke", XKB_KEY_Cyrillic_che_vertstroke }, - { "Cyrillic_de", XKB_KEY_Cyrillic_de }, - { "Cyrillic_DE", XKB_KEY_Cyrillic_DE }, - { "Cyrillic_dzhe", XKB_KEY_Cyrillic_dzhe }, - { "Cyrillic_DZHE", XKB_KEY_Cyrillic_DZHE }, - { "Cyrillic_e", XKB_KEY_Cyrillic_e }, - { "Cyrillic_E", XKB_KEY_Cyrillic_E }, - { "Cyrillic_ef", XKB_KEY_Cyrillic_ef }, - { "Cyrillic_EF", XKB_KEY_Cyrillic_EF }, - { "Cyrillic_el", XKB_KEY_Cyrillic_el }, - { "Cyrillic_EL", XKB_KEY_Cyrillic_EL }, - { "Cyrillic_em", XKB_KEY_Cyrillic_em }, - { "Cyrillic_EM", XKB_KEY_Cyrillic_EM }, - { "Cyrillic_en", XKB_KEY_Cyrillic_en }, - { "Cyrillic_EN", XKB_KEY_Cyrillic_EN }, - { "Cyrillic_EN_descender", XKB_KEY_Cyrillic_EN_descender }, - { "Cyrillic_en_descender", XKB_KEY_Cyrillic_en_descender }, - { "Cyrillic_er", XKB_KEY_Cyrillic_er }, - { "Cyrillic_ER", XKB_KEY_Cyrillic_ER }, - { "Cyrillic_es", XKB_KEY_Cyrillic_es }, - { "Cyrillic_ES", XKB_KEY_Cyrillic_ES }, - { "Cyrillic_ghe", XKB_KEY_Cyrillic_ghe }, - { "Cyrillic_GHE", XKB_KEY_Cyrillic_GHE }, - { "Cyrillic_GHE_bar", XKB_KEY_Cyrillic_GHE_bar }, - { "Cyrillic_ghe_bar", XKB_KEY_Cyrillic_ghe_bar }, - { "Cyrillic_ha", XKB_KEY_Cyrillic_ha }, - { "Cyrillic_HA", XKB_KEY_Cyrillic_HA }, - { "Cyrillic_HA_descender", XKB_KEY_Cyrillic_HA_descender }, - { "Cyrillic_ha_descender", XKB_KEY_Cyrillic_ha_descender }, - { "Cyrillic_hardsign", XKB_KEY_Cyrillic_hardsign }, - { "Cyrillic_HARDSIGN", XKB_KEY_Cyrillic_HARDSIGN }, - { "Cyrillic_i", XKB_KEY_Cyrillic_i }, - { "Cyrillic_I", XKB_KEY_Cyrillic_I }, - { "Cyrillic_I_macron", XKB_KEY_Cyrillic_I_macron }, - { "Cyrillic_i_macron", XKB_KEY_Cyrillic_i_macron }, - { "Cyrillic_ie", XKB_KEY_Cyrillic_ie }, - { "Cyrillic_IE", XKB_KEY_Cyrillic_IE }, - { "Cyrillic_io", XKB_KEY_Cyrillic_io }, - { "Cyrillic_IO", XKB_KEY_Cyrillic_IO }, - { "Cyrillic_je", XKB_KEY_Cyrillic_je }, - { "Cyrillic_JE", XKB_KEY_Cyrillic_JE }, - { "Cyrillic_ka", XKB_KEY_Cyrillic_ka }, - { "Cyrillic_KA", XKB_KEY_Cyrillic_KA }, - { "Cyrillic_KA_descender", XKB_KEY_Cyrillic_KA_descender }, - { "Cyrillic_ka_descender", XKB_KEY_Cyrillic_ka_descender }, - { "Cyrillic_KA_vertstroke", XKB_KEY_Cyrillic_KA_vertstroke }, - { "Cyrillic_ka_vertstroke", XKB_KEY_Cyrillic_ka_vertstroke }, - { "Cyrillic_lje", XKB_KEY_Cyrillic_lje }, - { "Cyrillic_LJE", XKB_KEY_Cyrillic_LJE }, - { "Cyrillic_nje", XKB_KEY_Cyrillic_nje }, - { "Cyrillic_NJE", XKB_KEY_Cyrillic_NJE }, - { "Cyrillic_o", XKB_KEY_Cyrillic_o }, - { "Cyrillic_O", XKB_KEY_Cyrillic_O }, - { "Cyrillic_O_bar", XKB_KEY_Cyrillic_O_bar }, - { "Cyrillic_o_bar", XKB_KEY_Cyrillic_o_bar }, - { "Cyrillic_pe", XKB_KEY_Cyrillic_pe }, - { "Cyrillic_PE", XKB_KEY_Cyrillic_PE }, - { "Cyrillic_SCHWA", XKB_KEY_Cyrillic_SCHWA }, - { "Cyrillic_schwa", XKB_KEY_Cyrillic_schwa }, - { "Cyrillic_sha", XKB_KEY_Cyrillic_sha }, - { "Cyrillic_SHA", XKB_KEY_Cyrillic_SHA }, - { "Cyrillic_shcha", XKB_KEY_Cyrillic_shcha }, - { "Cyrillic_SHCHA", XKB_KEY_Cyrillic_SHCHA }, - { "Cyrillic_SHHA", XKB_KEY_Cyrillic_SHHA }, - { "Cyrillic_shha", XKB_KEY_Cyrillic_shha }, - { "Cyrillic_shorti", XKB_KEY_Cyrillic_shorti }, - { "Cyrillic_SHORTI", XKB_KEY_Cyrillic_SHORTI }, - { "Cyrillic_softsign", XKB_KEY_Cyrillic_softsign }, - { "Cyrillic_SOFTSIGN", XKB_KEY_Cyrillic_SOFTSIGN }, - { "Cyrillic_te", XKB_KEY_Cyrillic_te }, - { "Cyrillic_TE", XKB_KEY_Cyrillic_TE }, - { "Cyrillic_tse", XKB_KEY_Cyrillic_tse }, - { "Cyrillic_TSE", XKB_KEY_Cyrillic_TSE }, - { "Cyrillic_u", XKB_KEY_Cyrillic_u }, - { "Cyrillic_U", XKB_KEY_Cyrillic_U }, - { "Cyrillic_U_macron", XKB_KEY_Cyrillic_U_macron }, - { "Cyrillic_u_macron", XKB_KEY_Cyrillic_u_macron }, - { "Cyrillic_U_straight", XKB_KEY_Cyrillic_U_straight }, - { "Cyrillic_u_straight", XKB_KEY_Cyrillic_u_straight }, - { "Cyrillic_U_straight_bar", XKB_KEY_Cyrillic_U_straight_bar }, - { "Cyrillic_u_straight_bar", XKB_KEY_Cyrillic_u_straight_bar }, - { "Cyrillic_ve", XKB_KEY_Cyrillic_ve }, - { "Cyrillic_VE", XKB_KEY_Cyrillic_VE }, - { "Cyrillic_ya", XKB_KEY_Cyrillic_ya }, - { "Cyrillic_YA", XKB_KEY_Cyrillic_YA }, - { "Cyrillic_yeru", XKB_KEY_Cyrillic_yeru }, - { "Cyrillic_YERU", XKB_KEY_Cyrillic_YERU }, - { "Cyrillic_yu", XKB_KEY_Cyrillic_yu }, - { "Cyrillic_YU", XKB_KEY_Cyrillic_YU }, - { "Cyrillic_ze", XKB_KEY_Cyrillic_ze }, - { "Cyrillic_ZE", XKB_KEY_Cyrillic_ZE }, - { "Cyrillic_zhe", XKB_KEY_Cyrillic_zhe }, - { "Cyrillic_ZHE", XKB_KEY_Cyrillic_ZHE }, - { "Cyrillic_ZHE_descender", XKB_KEY_Cyrillic_ZHE_descender }, - { "Cyrillic_zhe_descender", XKB_KEY_Cyrillic_zhe_descender }, - { "D", XKB_KEY_D }, - { "d", XKB_KEY_d }, - { "Dabovedot", XKB_KEY_Dabovedot }, - { "dabovedot", XKB_KEY_dabovedot }, - { "Dacute_accent", XKB_KEY_Dacute_accent }, - { "dagger", XKB_KEY_dagger }, - { "Dcaron", XKB_KEY_Dcaron }, - { "dcaron", XKB_KEY_dcaron }, - { "Dcedilla_accent", XKB_KEY_Dcedilla_accent }, - { "Dcircumflex_accent", XKB_KEY_Dcircumflex_accent }, - { "Ddiaeresis", XKB_KEY_Ddiaeresis }, - { "dead_a", XKB_KEY_dead_a }, - { "dead_A", XKB_KEY_dead_A }, - { "dead_abovecomma", XKB_KEY_dead_abovecomma }, - { "dead_abovedot", XKB_KEY_dead_abovedot }, - { "dead_abovereversedcomma", XKB_KEY_dead_abovereversedcomma }, - { "dead_abovering", XKB_KEY_dead_abovering }, - { "dead_acute", XKB_KEY_dead_acute }, - { "dead_belowbreve", XKB_KEY_dead_belowbreve }, - { "dead_belowcircumflex", XKB_KEY_dead_belowcircumflex }, - { "dead_belowcomma", XKB_KEY_dead_belowcomma }, - { "dead_belowdiaeresis", XKB_KEY_dead_belowdiaeresis }, - { "dead_belowdot", XKB_KEY_dead_belowdot }, - { "dead_belowmacron", XKB_KEY_dead_belowmacron }, - { "dead_belowring", XKB_KEY_dead_belowring }, - { "dead_belowtilde", XKB_KEY_dead_belowtilde }, - { "dead_breve", XKB_KEY_dead_breve }, - { "dead_capital_schwa", XKB_KEY_dead_capital_schwa }, - { "dead_caron", XKB_KEY_dead_caron }, - { "dead_cedilla", XKB_KEY_dead_cedilla }, - { "dead_circumflex", XKB_KEY_dead_circumflex }, - { "dead_currency", XKB_KEY_dead_currency }, - { "dead_dasia", XKB_KEY_dead_dasia }, - { "dead_diaeresis", XKB_KEY_dead_diaeresis }, - { "dead_doubleacute", XKB_KEY_dead_doubleacute }, - { "dead_doublegrave", XKB_KEY_dead_doublegrave }, - { "dead_e", XKB_KEY_dead_e }, - { "dead_E", XKB_KEY_dead_E }, - { "dead_grave", XKB_KEY_dead_grave }, - { "dead_greek", XKB_KEY_dead_greek }, - { "dead_hook", XKB_KEY_dead_hook }, - { "dead_horn", XKB_KEY_dead_horn }, - { "dead_i", XKB_KEY_dead_i }, - { "dead_I", XKB_KEY_dead_I }, - { "dead_invertedbreve", XKB_KEY_dead_invertedbreve }, - { "dead_iota", XKB_KEY_dead_iota }, - { "dead_macron", XKB_KEY_dead_macron }, - { "dead_o", XKB_KEY_dead_o }, - { "dead_O", XKB_KEY_dead_O }, - { "dead_ogonek", XKB_KEY_dead_ogonek }, - { "dead_perispomeni", XKB_KEY_dead_perispomeni }, - { "dead_psili", XKB_KEY_dead_psili }, - { "dead_semivoiced_sound", XKB_KEY_dead_semivoiced_sound }, - { "dead_small_schwa", XKB_KEY_dead_small_schwa }, - { "dead_stroke", XKB_KEY_dead_stroke }, - { "dead_tilde", XKB_KEY_dead_tilde }, - { "dead_u", XKB_KEY_dead_u }, - { "dead_U", XKB_KEY_dead_U }, - { "dead_voiced_sound", XKB_KEY_dead_voiced_sound }, - { "decimalpoint", XKB_KEY_decimalpoint }, - { "degree", XKB_KEY_degree }, - { "Delete", XKB_KEY_Delete }, - { "DeleteChar", XKB_KEY_DeleteChar }, - { "DeleteLine", XKB_KEY_DeleteLine }, - { "Dgrave_accent", XKB_KEY_Dgrave_accent }, - { "diaeresis", XKB_KEY_diaeresis }, - { "diamond", XKB_KEY_diamond }, - { "digitspace", XKB_KEY_digitspace }, - { "dintegral", XKB_KEY_dintegral }, - { "division", XKB_KEY_division }, - { "dollar", XKB_KEY_dollar }, - { "DongSign", XKB_KEY_DongSign }, - { "doubbaselinedot", XKB_KEY_doubbaselinedot }, - { "doubleacute", XKB_KEY_doubleacute }, - { "doubledagger", XKB_KEY_doubledagger }, - { "doublelowquotemark", XKB_KEY_doublelowquotemark }, - { "Down", XKB_KEY_Down }, - { "downarrow", XKB_KEY_downarrow }, - { "downcaret", XKB_KEY_downcaret }, - { "downshoe", XKB_KEY_downshoe }, - { "downstile", XKB_KEY_downstile }, - { "downtack", XKB_KEY_downtack }, - { "DRemove", XKB_KEY_DRemove }, - { "Dring_accent", XKB_KEY_Dring_accent }, - { "Dstroke", XKB_KEY_Dstroke }, - { "dstroke", XKB_KEY_dstroke }, - { "Dtilde", XKB_KEY_Dtilde }, - { "E", XKB_KEY_E }, - { "e", XKB_KEY_e }, - { "Eabovedot", XKB_KEY_Eabovedot }, - { "eabovedot", XKB_KEY_eabovedot }, - { "Eacute", XKB_KEY_Eacute }, - { "eacute", XKB_KEY_eacute }, - { "Ebelowdot", XKB_KEY_Ebelowdot }, - { "ebelowdot", XKB_KEY_ebelowdot }, - { "Ecaron", XKB_KEY_Ecaron }, - { "ecaron", XKB_KEY_ecaron }, - { "Ecircumflex", XKB_KEY_Ecircumflex }, - { "ecircumflex", XKB_KEY_ecircumflex }, - { "Ecircumflexacute", XKB_KEY_Ecircumflexacute }, - { "ecircumflexacute", XKB_KEY_ecircumflexacute }, - { "Ecircumflexbelowdot", XKB_KEY_Ecircumflexbelowdot }, - { "ecircumflexbelowdot", XKB_KEY_ecircumflexbelowdot }, - { "Ecircumflexgrave", XKB_KEY_Ecircumflexgrave }, - { "ecircumflexgrave", XKB_KEY_ecircumflexgrave }, - { "Ecircumflexhook", XKB_KEY_Ecircumflexhook }, - { "ecircumflexhook", XKB_KEY_ecircumflexhook }, - { "Ecircumflextilde", XKB_KEY_Ecircumflextilde }, - { "ecircumflextilde", XKB_KEY_ecircumflextilde }, - { "EcuSign", XKB_KEY_EcuSign }, - { "Ediaeresis", XKB_KEY_Ediaeresis }, - { "ediaeresis", XKB_KEY_ediaeresis }, - { "Egrave", XKB_KEY_Egrave }, - { "egrave", XKB_KEY_egrave }, - { "Ehook", XKB_KEY_Ehook }, - { "ehook", XKB_KEY_ehook }, - { "eightsubscript", XKB_KEY_eightsubscript }, - { "eightsuperior", XKB_KEY_eightsuperior }, - { "Eisu_Shift", XKB_KEY_Eisu_Shift }, - { "Eisu_toggle", XKB_KEY_Eisu_toggle }, - { "elementof", XKB_KEY_elementof }, - { "ellipsis", XKB_KEY_ellipsis }, - { "em3space", XKB_KEY_em3space }, - { "em4space", XKB_KEY_em4space }, - { "Emacron", XKB_KEY_Emacron }, - { "emacron", XKB_KEY_emacron }, - { "emdash", XKB_KEY_emdash }, - { "emfilledcircle", XKB_KEY_emfilledcircle }, - { "emfilledrect", XKB_KEY_emfilledrect }, - { "emopencircle", XKB_KEY_emopencircle }, - { "emopenrectangle", XKB_KEY_emopenrectangle }, - { "emptyset", XKB_KEY_emptyset }, - { "emspace", XKB_KEY_emspace }, - { "End", XKB_KEY_End }, - { "endash", XKB_KEY_endash }, - { "enfilledcircbullet", XKB_KEY_enfilledcircbullet }, - { "enfilledsqbullet", XKB_KEY_enfilledsqbullet }, - { "ENG", XKB_KEY_ENG }, - { "eng", XKB_KEY_eng }, - { "enopencircbullet", XKB_KEY_enopencircbullet }, - { "enopensquarebullet", XKB_KEY_enopensquarebullet }, - { "enspace", XKB_KEY_enspace }, - { "Eogonek", XKB_KEY_Eogonek }, - { "eogonek", XKB_KEY_eogonek }, - { "equal", XKB_KEY_equal }, - { "Escape", XKB_KEY_Escape }, - { "ETH", XKB_KEY_ETH }, - { "Eth", XKB_KEY_Eth }, - { "eth", XKB_KEY_eth }, - { "Etilde", XKB_KEY_Etilde }, - { "etilde", XKB_KEY_etilde }, - { "EuroSign", XKB_KEY_EuroSign }, - { "exclam", XKB_KEY_exclam }, - { "exclamdown", XKB_KEY_exclamdown }, - { "Execute", XKB_KEY_Execute }, - { "Ext16bit_L", XKB_KEY_Ext16bit_L }, - { "Ext16bit_R", XKB_KEY_Ext16bit_R }, - { "EZH", XKB_KEY_EZH }, - { "ezh", XKB_KEY_ezh }, - { "F", XKB_KEY_F }, - { "f", XKB_KEY_f }, - { "F1", XKB_KEY_F1 }, - { "F10", XKB_KEY_F10 }, - { "F11", XKB_KEY_F11 }, - { "F12", XKB_KEY_F12 }, - { "F13", XKB_KEY_F13 }, - { "F14", XKB_KEY_F14 }, - { "F15", XKB_KEY_F15 }, - { "F16", XKB_KEY_F16 }, - { "F17", XKB_KEY_F17 }, - { "F18", XKB_KEY_F18 }, - { "F19", XKB_KEY_F19 }, - { "F2", XKB_KEY_F2 }, - { "F20", XKB_KEY_F20 }, - { "F21", XKB_KEY_F21 }, - { "F22", XKB_KEY_F22 }, - { "F23", XKB_KEY_F23 }, - { "F24", XKB_KEY_F24 }, - { "F25", XKB_KEY_F25 }, - { "F26", XKB_KEY_F26 }, - { "F27", XKB_KEY_F27 }, - { "F28", XKB_KEY_F28 }, - { "F29", XKB_KEY_F29 }, - { "F3", XKB_KEY_F3 }, - { "F30", XKB_KEY_F30 }, - { "F31", XKB_KEY_F31 }, - { "F32", XKB_KEY_F32 }, - { "F33", XKB_KEY_F33 }, - { "F34", XKB_KEY_F34 }, - { "F35", XKB_KEY_F35 }, - { "F4", XKB_KEY_F4 }, - { "F5", XKB_KEY_F5 }, - { "F6", XKB_KEY_F6 }, - { "F7", XKB_KEY_F7 }, - { "F8", XKB_KEY_F8 }, - { "F9", XKB_KEY_F9 }, - { "Fabovedot", XKB_KEY_Fabovedot }, - { "fabovedot", XKB_KEY_fabovedot }, - { "Farsi_0", XKB_KEY_Farsi_0 }, - { "Farsi_1", XKB_KEY_Farsi_1 }, - { "Farsi_2", XKB_KEY_Farsi_2 }, - { "Farsi_3", XKB_KEY_Farsi_3 }, - { "Farsi_4", XKB_KEY_Farsi_4 }, - { "Farsi_5", XKB_KEY_Farsi_5 }, - { "Farsi_6", XKB_KEY_Farsi_6 }, - { "Farsi_7", XKB_KEY_Farsi_7 }, - { "Farsi_8", XKB_KEY_Farsi_8 }, - { "Farsi_9", XKB_KEY_Farsi_9 }, - { "Farsi_yeh", XKB_KEY_Farsi_yeh }, - { "femalesymbol", XKB_KEY_femalesymbol }, - { "ff", XKB_KEY_ff }, - { "FFrancSign", XKB_KEY_FFrancSign }, - { "figdash", XKB_KEY_figdash }, - { "filledlefttribullet", XKB_KEY_filledlefttribullet }, - { "filledrectbullet", XKB_KEY_filledrectbullet }, - { "filledrighttribullet", XKB_KEY_filledrighttribullet }, - { "filledtribulletdown", XKB_KEY_filledtribulletdown }, - { "filledtribulletup", XKB_KEY_filledtribulletup }, - { "Find", XKB_KEY_Find }, - { "First_Virtual_Screen", XKB_KEY_First_Virtual_Screen }, - { "fiveeighths", XKB_KEY_fiveeighths }, - { "fivesixths", XKB_KEY_fivesixths }, - { "fivesubscript", XKB_KEY_fivesubscript }, - { "fivesuperior", XKB_KEY_fivesuperior }, - { "fourfifths", XKB_KEY_fourfifths }, - { "foursubscript", XKB_KEY_foursubscript }, - { "foursuperior", XKB_KEY_foursuperior }, - { "fourthroot", XKB_KEY_fourthroot }, - { "function", XKB_KEY_function }, - { "G", XKB_KEY_G }, - { "g", XKB_KEY_g }, - { "Gabovedot", XKB_KEY_Gabovedot }, - { "gabovedot", XKB_KEY_gabovedot }, - { "Gbreve", XKB_KEY_Gbreve }, - { "gbreve", XKB_KEY_gbreve }, - { "Gcaron", XKB_KEY_Gcaron }, - { "gcaron", XKB_KEY_gcaron }, - { "Gcedilla", XKB_KEY_Gcedilla }, - { "gcedilla", XKB_KEY_gcedilla }, - { "Gcircumflex", XKB_KEY_Gcircumflex }, - { "gcircumflex", XKB_KEY_gcircumflex }, - { "Georgian_an", XKB_KEY_Georgian_an }, - { "Georgian_ban", XKB_KEY_Georgian_ban }, - { "Georgian_can", XKB_KEY_Georgian_can }, - { "Georgian_char", XKB_KEY_Georgian_char }, - { "Georgian_chin", XKB_KEY_Georgian_chin }, - { "Georgian_cil", XKB_KEY_Georgian_cil }, - { "Georgian_don", XKB_KEY_Georgian_don }, - { "Georgian_en", XKB_KEY_Georgian_en }, - { "Georgian_fi", XKB_KEY_Georgian_fi }, - { "Georgian_gan", XKB_KEY_Georgian_gan }, - { "Georgian_ghan", XKB_KEY_Georgian_ghan }, - { "Georgian_hae", XKB_KEY_Georgian_hae }, - { "Georgian_har", XKB_KEY_Georgian_har }, - { "Georgian_he", XKB_KEY_Georgian_he }, - { "Georgian_hie", XKB_KEY_Georgian_hie }, - { "Georgian_hoe", XKB_KEY_Georgian_hoe }, - { "Georgian_in", XKB_KEY_Georgian_in }, - { "Georgian_jhan", XKB_KEY_Georgian_jhan }, - { "Georgian_jil", XKB_KEY_Georgian_jil }, - { "Georgian_kan", XKB_KEY_Georgian_kan }, - { "Georgian_khar", XKB_KEY_Georgian_khar }, - { "Georgian_las", XKB_KEY_Georgian_las }, - { "Georgian_man", XKB_KEY_Georgian_man }, - { "Georgian_nar", XKB_KEY_Georgian_nar }, - { "Georgian_on", XKB_KEY_Georgian_on }, - { "Georgian_par", XKB_KEY_Georgian_par }, - { "Georgian_phar", XKB_KEY_Georgian_phar }, - { "Georgian_qar", XKB_KEY_Georgian_qar }, - { "Georgian_rae", XKB_KEY_Georgian_rae }, - { "Georgian_san", XKB_KEY_Georgian_san }, - { "Georgian_shin", XKB_KEY_Georgian_shin }, - { "Georgian_tan", XKB_KEY_Georgian_tan }, - { "Georgian_tar", XKB_KEY_Georgian_tar }, - { "Georgian_un", XKB_KEY_Georgian_un }, - { "Georgian_vin", XKB_KEY_Georgian_vin }, - { "Georgian_we", XKB_KEY_Georgian_we }, - { "Georgian_xan", XKB_KEY_Georgian_xan }, - { "Georgian_zen", XKB_KEY_Georgian_zen }, - { "Georgian_zhar", XKB_KEY_Georgian_zhar }, - { "grave", XKB_KEY_grave }, - { "greater", XKB_KEY_greater }, - { "greaterthanequal", XKB_KEY_greaterthanequal }, - { "Greek_accentdieresis", XKB_KEY_Greek_accentdieresis }, - { "Greek_ALPHA", XKB_KEY_Greek_ALPHA }, - { "Greek_alpha", XKB_KEY_Greek_alpha }, - { "Greek_ALPHAaccent", XKB_KEY_Greek_ALPHAaccent }, - { "Greek_alphaaccent", XKB_KEY_Greek_alphaaccent }, - { "Greek_BETA", XKB_KEY_Greek_BETA }, - { "Greek_beta", XKB_KEY_Greek_beta }, - { "Greek_CHI", XKB_KEY_Greek_CHI }, - { "Greek_chi", XKB_KEY_Greek_chi }, - { "Greek_DELTA", XKB_KEY_Greek_DELTA }, - { "Greek_delta", XKB_KEY_Greek_delta }, - { "Greek_EPSILON", XKB_KEY_Greek_EPSILON }, - { "Greek_epsilon", XKB_KEY_Greek_epsilon }, - { "Greek_EPSILONaccent", XKB_KEY_Greek_EPSILONaccent }, - { "Greek_epsilonaccent", XKB_KEY_Greek_epsilonaccent }, - { "Greek_ETA", XKB_KEY_Greek_ETA }, - { "Greek_eta", XKB_KEY_Greek_eta }, - { "Greek_ETAaccent", XKB_KEY_Greek_ETAaccent }, - { "Greek_etaaccent", XKB_KEY_Greek_etaaccent }, - { "Greek_finalsmallsigma", XKB_KEY_Greek_finalsmallsigma }, - { "Greek_GAMMA", XKB_KEY_Greek_GAMMA }, - { "Greek_gamma", XKB_KEY_Greek_gamma }, - { "Greek_horizbar", XKB_KEY_Greek_horizbar }, - { "Greek_IOTA", XKB_KEY_Greek_IOTA }, - { "Greek_iota", XKB_KEY_Greek_iota }, - { "Greek_IOTAaccent", XKB_KEY_Greek_IOTAaccent }, - { "Greek_iotaaccent", XKB_KEY_Greek_iotaaccent }, - { "Greek_iotaaccentdieresis", XKB_KEY_Greek_iotaaccentdieresis }, - { "Greek_IOTAdiaeresis", XKB_KEY_Greek_IOTAdiaeresis }, - { "Greek_IOTAdieresis", XKB_KEY_Greek_IOTAdieresis }, - { "Greek_iotadieresis", XKB_KEY_Greek_iotadieresis }, - { "Greek_KAPPA", XKB_KEY_Greek_KAPPA }, - { "Greek_kappa", XKB_KEY_Greek_kappa }, - { "Greek_LAMBDA", XKB_KEY_Greek_LAMBDA }, - { "Greek_lambda", XKB_KEY_Greek_lambda }, - { "Greek_LAMDA", XKB_KEY_Greek_LAMDA }, - { "Greek_lamda", XKB_KEY_Greek_lamda }, - { "Greek_MU", XKB_KEY_Greek_MU }, - { "Greek_mu", XKB_KEY_Greek_mu }, - { "Greek_NU", XKB_KEY_Greek_NU }, - { "Greek_nu", XKB_KEY_Greek_nu }, - { "Greek_OMEGA", XKB_KEY_Greek_OMEGA }, - { "Greek_omega", XKB_KEY_Greek_omega }, - { "Greek_OMEGAaccent", XKB_KEY_Greek_OMEGAaccent }, - { "Greek_omegaaccent", XKB_KEY_Greek_omegaaccent }, - { "Greek_OMICRON", XKB_KEY_Greek_OMICRON }, - { "Greek_omicron", XKB_KEY_Greek_omicron }, - { "Greek_OMICRONaccent", XKB_KEY_Greek_OMICRONaccent }, - { "Greek_omicronaccent", XKB_KEY_Greek_omicronaccent }, - { "Greek_PHI", XKB_KEY_Greek_PHI }, - { "Greek_phi", XKB_KEY_Greek_phi }, - { "Greek_PI", XKB_KEY_Greek_PI }, - { "Greek_pi", XKB_KEY_Greek_pi }, - { "Greek_PSI", XKB_KEY_Greek_PSI }, - { "Greek_psi", XKB_KEY_Greek_psi }, - { "Greek_RHO", XKB_KEY_Greek_RHO }, - { "Greek_rho", XKB_KEY_Greek_rho }, - { "Greek_SIGMA", XKB_KEY_Greek_SIGMA }, - { "Greek_sigma", XKB_KEY_Greek_sigma }, - { "Greek_switch", XKB_KEY_Greek_switch }, - { "Greek_TAU", XKB_KEY_Greek_TAU }, - { "Greek_tau", XKB_KEY_Greek_tau }, - { "Greek_THETA", XKB_KEY_Greek_THETA }, - { "Greek_theta", XKB_KEY_Greek_theta }, - { "Greek_UPSILON", XKB_KEY_Greek_UPSILON }, - { "Greek_upsilon", XKB_KEY_Greek_upsilon }, - { "Greek_UPSILONaccent", XKB_KEY_Greek_UPSILONaccent }, - { "Greek_upsilonaccent", XKB_KEY_Greek_upsilonaccent }, - { "Greek_upsilonaccentdieresis", XKB_KEY_Greek_upsilonaccentdieresis }, - { "Greek_UPSILONdieresis", XKB_KEY_Greek_UPSILONdieresis }, - { "Greek_upsilondieresis", XKB_KEY_Greek_upsilondieresis }, - { "Greek_XI", XKB_KEY_Greek_XI }, - { "Greek_xi", XKB_KEY_Greek_xi }, - { "Greek_ZETA", XKB_KEY_Greek_ZETA }, - { "Greek_zeta", XKB_KEY_Greek_zeta }, - { "guilder", XKB_KEY_guilder }, - { "guillemotleft", XKB_KEY_guillemotleft }, - { "guillemotright", XKB_KEY_guillemotright }, - { "H", XKB_KEY_H }, - { "h", XKB_KEY_h }, - { "hairspace", XKB_KEY_hairspace }, - { "Hangul", XKB_KEY_Hangul }, - { "Hangul_A", XKB_KEY_Hangul_A }, - { "Hangul_AE", XKB_KEY_Hangul_AE }, - { "Hangul_AraeA", XKB_KEY_Hangul_AraeA }, - { "Hangul_AraeAE", XKB_KEY_Hangul_AraeAE }, - { "Hangul_Banja", XKB_KEY_Hangul_Banja }, - { "Hangul_Cieuc", XKB_KEY_Hangul_Cieuc }, - { "Hangul_Codeinput", XKB_KEY_Hangul_Codeinput }, - { "Hangul_Dikeud", XKB_KEY_Hangul_Dikeud }, - { "Hangul_E", XKB_KEY_Hangul_E }, - { "Hangul_End", XKB_KEY_Hangul_End }, - { "Hangul_EO", XKB_KEY_Hangul_EO }, - { "Hangul_EU", XKB_KEY_Hangul_EU }, - { "Hangul_Hanja", XKB_KEY_Hangul_Hanja }, - { "Hangul_Hieuh", XKB_KEY_Hangul_Hieuh }, - { "Hangul_I", XKB_KEY_Hangul_I }, - { "Hangul_Ieung", XKB_KEY_Hangul_Ieung }, - { "Hangul_J_Cieuc", XKB_KEY_Hangul_J_Cieuc }, - { "Hangul_J_Dikeud", XKB_KEY_Hangul_J_Dikeud }, - { "Hangul_J_Hieuh", XKB_KEY_Hangul_J_Hieuh }, - { "Hangul_J_Ieung", XKB_KEY_Hangul_J_Ieung }, - { "Hangul_J_Jieuj", XKB_KEY_Hangul_J_Jieuj }, - { "Hangul_J_Khieuq", XKB_KEY_Hangul_J_Khieuq }, - { "Hangul_J_Kiyeog", XKB_KEY_Hangul_J_Kiyeog }, - { "Hangul_J_KiyeogSios", XKB_KEY_Hangul_J_KiyeogSios }, - { "Hangul_J_KkogjiDalrinIeung", XKB_KEY_Hangul_J_KkogjiDalrinIeung }, - { "Hangul_J_Mieum", XKB_KEY_Hangul_J_Mieum }, - { "Hangul_J_Nieun", XKB_KEY_Hangul_J_Nieun }, - { "Hangul_J_NieunHieuh", XKB_KEY_Hangul_J_NieunHieuh }, - { "Hangul_J_NieunJieuj", XKB_KEY_Hangul_J_NieunJieuj }, - { "Hangul_J_PanSios", XKB_KEY_Hangul_J_PanSios }, - { "Hangul_J_Phieuf", XKB_KEY_Hangul_J_Phieuf }, - { "Hangul_J_Pieub", XKB_KEY_Hangul_J_Pieub }, - { "Hangul_J_PieubSios", XKB_KEY_Hangul_J_PieubSios }, - { "Hangul_J_Rieul", XKB_KEY_Hangul_J_Rieul }, - { "Hangul_J_RieulHieuh", XKB_KEY_Hangul_J_RieulHieuh }, - { "Hangul_J_RieulKiyeog", XKB_KEY_Hangul_J_RieulKiyeog }, - { "Hangul_J_RieulMieum", XKB_KEY_Hangul_J_RieulMieum }, - { "Hangul_J_RieulPhieuf", XKB_KEY_Hangul_J_RieulPhieuf }, - { "Hangul_J_RieulPieub", XKB_KEY_Hangul_J_RieulPieub }, - { "Hangul_J_RieulSios", XKB_KEY_Hangul_J_RieulSios }, - { "Hangul_J_RieulTieut", XKB_KEY_Hangul_J_RieulTieut }, - { "Hangul_J_Sios", XKB_KEY_Hangul_J_Sios }, - { "Hangul_J_SsangKiyeog", XKB_KEY_Hangul_J_SsangKiyeog }, - { "Hangul_J_SsangSios", XKB_KEY_Hangul_J_SsangSios }, - { "Hangul_J_Tieut", XKB_KEY_Hangul_J_Tieut }, - { "Hangul_J_YeorinHieuh", XKB_KEY_Hangul_J_YeorinHieuh }, - { "Hangul_Jamo", XKB_KEY_Hangul_Jamo }, - { "Hangul_Jeonja", XKB_KEY_Hangul_Jeonja }, - { "Hangul_Jieuj", XKB_KEY_Hangul_Jieuj }, - { "Hangul_Khieuq", XKB_KEY_Hangul_Khieuq }, - { "Hangul_Kiyeog", XKB_KEY_Hangul_Kiyeog }, - { "Hangul_KiyeogSios", XKB_KEY_Hangul_KiyeogSios }, - { "Hangul_KkogjiDalrinIeung", XKB_KEY_Hangul_KkogjiDalrinIeung }, - { "Hangul_Mieum", XKB_KEY_Hangul_Mieum }, - { "Hangul_MultipleCandidate", XKB_KEY_Hangul_MultipleCandidate }, - { "Hangul_Nieun", XKB_KEY_Hangul_Nieun }, - { "Hangul_NieunHieuh", XKB_KEY_Hangul_NieunHieuh }, - { "Hangul_NieunJieuj", XKB_KEY_Hangul_NieunJieuj }, - { "Hangul_O", XKB_KEY_Hangul_O }, - { "Hangul_OE", XKB_KEY_Hangul_OE }, - { "Hangul_PanSios", XKB_KEY_Hangul_PanSios }, - { "Hangul_Phieuf", XKB_KEY_Hangul_Phieuf }, - { "Hangul_Pieub", XKB_KEY_Hangul_Pieub }, - { "Hangul_PieubSios", XKB_KEY_Hangul_PieubSios }, - { "Hangul_PostHanja", XKB_KEY_Hangul_PostHanja }, - { "Hangul_PreHanja", XKB_KEY_Hangul_PreHanja }, - { "Hangul_PreviousCandidate", XKB_KEY_Hangul_PreviousCandidate }, - { "Hangul_Rieul", XKB_KEY_Hangul_Rieul }, - { "Hangul_RieulHieuh", XKB_KEY_Hangul_RieulHieuh }, - { "Hangul_RieulKiyeog", XKB_KEY_Hangul_RieulKiyeog }, - { "Hangul_RieulMieum", XKB_KEY_Hangul_RieulMieum }, - { "Hangul_RieulPhieuf", XKB_KEY_Hangul_RieulPhieuf }, - { "Hangul_RieulPieub", XKB_KEY_Hangul_RieulPieub }, - { "Hangul_RieulSios", XKB_KEY_Hangul_RieulSios }, - { "Hangul_RieulTieut", XKB_KEY_Hangul_RieulTieut }, - { "Hangul_RieulYeorinHieuh", XKB_KEY_Hangul_RieulYeorinHieuh }, - { "Hangul_Romaja", XKB_KEY_Hangul_Romaja }, - { "Hangul_SingleCandidate", XKB_KEY_Hangul_SingleCandidate }, - { "Hangul_Sios", XKB_KEY_Hangul_Sios }, - { "Hangul_Special", XKB_KEY_Hangul_Special }, - { "Hangul_SsangDikeud", XKB_KEY_Hangul_SsangDikeud }, - { "Hangul_SsangJieuj", XKB_KEY_Hangul_SsangJieuj }, - { "Hangul_SsangKiyeog", XKB_KEY_Hangul_SsangKiyeog }, - { "Hangul_SsangPieub", XKB_KEY_Hangul_SsangPieub }, - { "Hangul_SsangSios", XKB_KEY_Hangul_SsangSios }, - { "Hangul_Start", XKB_KEY_Hangul_Start }, - { "Hangul_SunkyeongeumMieum", XKB_KEY_Hangul_SunkyeongeumMieum }, - { "Hangul_SunkyeongeumPhieuf", XKB_KEY_Hangul_SunkyeongeumPhieuf }, - { "Hangul_SunkyeongeumPieub", XKB_KEY_Hangul_SunkyeongeumPieub }, - { "Hangul_switch", XKB_KEY_Hangul_switch }, - { "Hangul_Tieut", XKB_KEY_Hangul_Tieut }, - { "Hangul_U", XKB_KEY_Hangul_U }, - { "Hangul_WA", XKB_KEY_Hangul_WA }, - { "Hangul_WAE", XKB_KEY_Hangul_WAE }, - { "Hangul_WE", XKB_KEY_Hangul_WE }, - { "Hangul_WEO", XKB_KEY_Hangul_WEO }, - { "Hangul_WI", XKB_KEY_Hangul_WI }, - { "Hangul_YA", XKB_KEY_Hangul_YA }, - { "Hangul_YAE", XKB_KEY_Hangul_YAE }, - { "Hangul_YE", XKB_KEY_Hangul_YE }, - { "Hangul_YEO", XKB_KEY_Hangul_YEO }, - { "Hangul_YeorinHieuh", XKB_KEY_Hangul_YeorinHieuh }, - { "Hangul_YI", XKB_KEY_Hangul_YI }, - { "Hangul_YO", XKB_KEY_Hangul_YO }, - { "Hangul_YU", XKB_KEY_Hangul_YU }, - { "Hankaku", XKB_KEY_Hankaku }, - { "Hcircumflex", XKB_KEY_Hcircumflex }, - { "hcircumflex", XKB_KEY_hcircumflex }, - { "heart", XKB_KEY_heart }, - { "hebrew_aleph", XKB_KEY_hebrew_aleph }, - { "hebrew_ayin", XKB_KEY_hebrew_ayin }, - { "hebrew_bet", XKB_KEY_hebrew_bet }, - { "hebrew_beth", XKB_KEY_hebrew_beth }, - { "hebrew_chet", XKB_KEY_hebrew_chet }, - { "hebrew_dalet", XKB_KEY_hebrew_dalet }, - { "hebrew_daleth", XKB_KEY_hebrew_daleth }, - { "hebrew_doublelowline", XKB_KEY_hebrew_doublelowline }, - { "hebrew_finalkaph", XKB_KEY_hebrew_finalkaph }, - { "hebrew_finalmem", XKB_KEY_hebrew_finalmem }, - { "hebrew_finalnun", XKB_KEY_hebrew_finalnun }, - { "hebrew_finalpe", XKB_KEY_hebrew_finalpe }, - { "hebrew_finalzade", XKB_KEY_hebrew_finalzade }, - { "hebrew_finalzadi", XKB_KEY_hebrew_finalzadi }, - { "hebrew_gimel", XKB_KEY_hebrew_gimel }, - { "hebrew_gimmel", XKB_KEY_hebrew_gimmel }, - { "hebrew_he", XKB_KEY_hebrew_he }, - { "hebrew_het", XKB_KEY_hebrew_het }, - { "hebrew_kaph", XKB_KEY_hebrew_kaph }, - { "hebrew_kuf", XKB_KEY_hebrew_kuf }, - { "hebrew_lamed", XKB_KEY_hebrew_lamed }, - { "hebrew_mem", XKB_KEY_hebrew_mem }, - { "hebrew_nun", XKB_KEY_hebrew_nun }, - { "hebrew_pe", XKB_KEY_hebrew_pe }, - { "hebrew_qoph", XKB_KEY_hebrew_qoph }, - { "hebrew_resh", XKB_KEY_hebrew_resh }, - { "hebrew_samech", XKB_KEY_hebrew_samech }, - { "hebrew_samekh", XKB_KEY_hebrew_samekh }, - { "hebrew_shin", XKB_KEY_hebrew_shin }, - { "Hebrew_switch", XKB_KEY_Hebrew_switch }, - { "hebrew_taf", XKB_KEY_hebrew_taf }, - { "hebrew_taw", XKB_KEY_hebrew_taw }, - { "hebrew_tet", XKB_KEY_hebrew_tet }, - { "hebrew_teth", XKB_KEY_hebrew_teth }, - { "hebrew_waw", XKB_KEY_hebrew_waw }, - { "hebrew_yod", XKB_KEY_hebrew_yod }, - { "hebrew_zade", XKB_KEY_hebrew_zade }, - { "hebrew_zadi", XKB_KEY_hebrew_zadi }, - { "hebrew_zain", XKB_KEY_hebrew_zain }, - { "hebrew_zayin", XKB_KEY_hebrew_zayin }, - { "Help", XKB_KEY_Help }, - { "Henkan", XKB_KEY_Henkan }, - { "Henkan_Mode", XKB_KEY_Henkan_Mode }, - { "hexagram", XKB_KEY_hexagram }, - { "Hiragana", XKB_KEY_Hiragana }, - { "Hiragana_Katakana", XKB_KEY_Hiragana_Katakana }, - { "Home", XKB_KEY_Home }, - { "horizconnector", XKB_KEY_horizconnector }, - { "horizlinescan1", XKB_KEY_horizlinescan1 }, - { "horizlinescan3", XKB_KEY_horizlinescan3 }, - { "horizlinescan5", XKB_KEY_horizlinescan5 }, - { "horizlinescan7", XKB_KEY_horizlinescan7 }, - { "horizlinescan9", XKB_KEY_horizlinescan9 }, - { "hpBackTab", XKB_KEY_hpBackTab }, - { "hpblock", XKB_KEY_hpblock }, - { "hpClearLine", XKB_KEY_hpClearLine }, - { "hpDeleteChar", XKB_KEY_hpDeleteChar }, - { "hpDeleteLine", XKB_KEY_hpDeleteLine }, - { "hpguilder", XKB_KEY_hpguilder }, - { "hpInsertChar", XKB_KEY_hpInsertChar }, - { "hpInsertLine", XKB_KEY_hpInsertLine }, - { "hpIO", XKB_KEY_hpIO }, - { "hpKP_BackTab", XKB_KEY_hpKP_BackTab }, - { "hplira", XKB_KEY_hplira }, - { "hplongminus", XKB_KEY_hplongminus }, - { "hpModelock1", XKB_KEY_hpModelock1 }, - { "hpModelock2", XKB_KEY_hpModelock2 }, - { "hpmute_acute", XKB_KEY_hpmute_acute }, - { "hpmute_asciicircum", XKB_KEY_hpmute_asciicircum }, - { "hpmute_asciitilde", XKB_KEY_hpmute_asciitilde }, - { "hpmute_diaeresis", XKB_KEY_hpmute_diaeresis }, - { "hpmute_grave", XKB_KEY_hpmute_grave }, - { "hpReset", XKB_KEY_hpReset }, - { "hpSystem", XKB_KEY_hpSystem }, - { "hpUser", XKB_KEY_hpUser }, - { "hpYdiaeresis", XKB_KEY_hpYdiaeresis }, - { "Hstroke", XKB_KEY_Hstroke }, - { "hstroke", XKB_KEY_hstroke }, - { "ht", XKB_KEY_ht }, - { "Hyper_L", XKB_KEY_Hyper_L }, - { "Hyper_R", XKB_KEY_Hyper_R }, - { "hyphen", XKB_KEY_hyphen }, - { "I", XKB_KEY_I }, - { "i", XKB_KEY_i }, - { "Iabovedot", XKB_KEY_Iabovedot }, - { "Iacute", XKB_KEY_Iacute }, - { "iacute", XKB_KEY_iacute }, - { "Ibelowdot", XKB_KEY_Ibelowdot }, - { "ibelowdot", XKB_KEY_ibelowdot }, - { "Ibreve", XKB_KEY_Ibreve }, - { "ibreve", XKB_KEY_ibreve }, - { "Icircumflex", XKB_KEY_Icircumflex }, - { "icircumflex", XKB_KEY_icircumflex }, - { "identical", XKB_KEY_identical }, - { "Idiaeresis", XKB_KEY_Idiaeresis }, - { "idiaeresis", XKB_KEY_idiaeresis }, - { "idotless", XKB_KEY_idotless }, - { "ifonlyif", XKB_KEY_ifonlyif }, - { "Igrave", XKB_KEY_Igrave }, - { "igrave", XKB_KEY_igrave }, - { "Ihook", XKB_KEY_Ihook }, - { "ihook", XKB_KEY_ihook }, - { "Imacron", XKB_KEY_Imacron }, - { "imacron", XKB_KEY_imacron }, - { "implies", XKB_KEY_implies }, - { "includedin", XKB_KEY_includedin }, - { "includes", XKB_KEY_includes }, - { "infinity", XKB_KEY_infinity }, - { "Insert", XKB_KEY_Insert }, - { "InsertChar", XKB_KEY_InsertChar }, - { "InsertLine", XKB_KEY_InsertLine }, - { "integral", XKB_KEY_integral }, - { "intersection", XKB_KEY_intersection }, - { "IO", XKB_KEY_IO }, - { "Iogonek", XKB_KEY_Iogonek }, - { "iogonek", XKB_KEY_iogonek }, - { "ISO_Center_Object", XKB_KEY_ISO_Center_Object }, - { "ISO_Continuous_Underline", XKB_KEY_ISO_Continuous_Underline }, - { "ISO_Discontinuous_Underline", XKB_KEY_ISO_Discontinuous_Underline }, - { "ISO_Emphasize", XKB_KEY_ISO_Emphasize }, - { "ISO_Enter", XKB_KEY_ISO_Enter }, - { "ISO_Fast_Cursor_Down", XKB_KEY_ISO_Fast_Cursor_Down }, - { "ISO_Fast_Cursor_Left", XKB_KEY_ISO_Fast_Cursor_Left }, - { "ISO_Fast_Cursor_Right", XKB_KEY_ISO_Fast_Cursor_Right }, - { "ISO_Fast_Cursor_Up", XKB_KEY_ISO_Fast_Cursor_Up }, - { "ISO_First_Group", XKB_KEY_ISO_First_Group }, - { "ISO_First_Group_Lock", XKB_KEY_ISO_First_Group_Lock }, - { "ISO_Group_Latch", XKB_KEY_ISO_Group_Latch }, - { "ISO_Group_Lock", XKB_KEY_ISO_Group_Lock }, - { "ISO_Group_Shift", XKB_KEY_ISO_Group_Shift }, - { "ISO_Last_Group", XKB_KEY_ISO_Last_Group }, - { "ISO_Last_Group_Lock", XKB_KEY_ISO_Last_Group_Lock }, - { "ISO_Left_Tab", XKB_KEY_ISO_Left_Tab }, - { "ISO_Level2_Latch", XKB_KEY_ISO_Level2_Latch }, - { "ISO_Level3_Latch", XKB_KEY_ISO_Level3_Latch }, - { "ISO_Level3_Lock", XKB_KEY_ISO_Level3_Lock }, - { "ISO_Level3_Shift", XKB_KEY_ISO_Level3_Shift }, - { "ISO_Level5_Latch", XKB_KEY_ISO_Level5_Latch }, - { "ISO_Level5_Lock", XKB_KEY_ISO_Level5_Lock }, - { "ISO_Level5_Shift", XKB_KEY_ISO_Level5_Shift }, - { "ISO_Lock", XKB_KEY_ISO_Lock }, - { "ISO_Move_Line_Down", XKB_KEY_ISO_Move_Line_Down }, - { "ISO_Move_Line_Up", XKB_KEY_ISO_Move_Line_Up }, - { "ISO_Next_Group", XKB_KEY_ISO_Next_Group }, - { "ISO_Next_Group_Lock", XKB_KEY_ISO_Next_Group_Lock }, - { "ISO_Partial_Line_Down", XKB_KEY_ISO_Partial_Line_Down }, - { "ISO_Partial_Line_Up", XKB_KEY_ISO_Partial_Line_Up }, - { "ISO_Partial_Space_Left", XKB_KEY_ISO_Partial_Space_Left }, - { "ISO_Partial_Space_Right", XKB_KEY_ISO_Partial_Space_Right }, - { "ISO_Prev_Group", XKB_KEY_ISO_Prev_Group }, - { "ISO_Prev_Group_Lock", XKB_KEY_ISO_Prev_Group_Lock }, - { "ISO_Release_Both_Margins", XKB_KEY_ISO_Release_Both_Margins }, - { "ISO_Release_Margin_Left", XKB_KEY_ISO_Release_Margin_Left }, - { "ISO_Release_Margin_Right", XKB_KEY_ISO_Release_Margin_Right }, - { "ISO_Set_Margin_Left", XKB_KEY_ISO_Set_Margin_Left }, - { "ISO_Set_Margin_Right", XKB_KEY_ISO_Set_Margin_Right }, - { "Itilde", XKB_KEY_Itilde }, - { "itilde", XKB_KEY_itilde }, - { "J", XKB_KEY_J }, - { "j", XKB_KEY_j }, - { "Jcircumflex", XKB_KEY_Jcircumflex }, - { "jcircumflex", XKB_KEY_jcircumflex }, - { "jot", XKB_KEY_jot }, - { "K", XKB_KEY_K }, - { "k", XKB_KEY_k }, - { "kana_a", XKB_KEY_kana_a }, - { "kana_A", XKB_KEY_kana_A }, - { "kana_CHI", XKB_KEY_kana_CHI }, - { "kana_closingbracket", XKB_KEY_kana_closingbracket }, - { "kana_comma", XKB_KEY_kana_comma }, - { "kana_conjunctive", XKB_KEY_kana_conjunctive }, - { "kana_e", XKB_KEY_kana_e }, - { "kana_E", XKB_KEY_kana_E }, - { "kana_FU", XKB_KEY_kana_FU }, - { "kana_fullstop", XKB_KEY_kana_fullstop }, - { "kana_HA", XKB_KEY_kana_HA }, - { "kana_HE", XKB_KEY_kana_HE }, - { "kana_HI", XKB_KEY_kana_HI }, - { "kana_HO", XKB_KEY_kana_HO }, - { "kana_HU", XKB_KEY_kana_HU }, - { "kana_i", XKB_KEY_kana_i }, - { "kana_I", XKB_KEY_kana_I }, - { "kana_KA", XKB_KEY_kana_KA }, - { "kana_KE", XKB_KEY_kana_KE }, - { "kana_KI", XKB_KEY_kana_KI }, - { "kana_KO", XKB_KEY_kana_KO }, - { "kana_KU", XKB_KEY_kana_KU }, - { "Kana_Lock", XKB_KEY_Kana_Lock }, - { "kana_MA", XKB_KEY_kana_MA }, - { "kana_ME", XKB_KEY_kana_ME }, - { "kana_MI", XKB_KEY_kana_MI }, - { "kana_middledot", XKB_KEY_kana_middledot }, - { "kana_MO", XKB_KEY_kana_MO }, - { "kana_MU", XKB_KEY_kana_MU }, - { "kana_N", XKB_KEY_kana_N }, - { "kana_NA", XKB_KEY_kana_NA }, - { "kana_NE", XKB_KEY_kana_NE }, - { "kana_NI", XKB_KEY_kana_NI }, - { "kana_NO", XKB_KEY_kana_NO }, - { "kana_NU", XKB_KEY_kana_NU }, - { "kana_o", XKB_KEY_kana_o }, - { "kana_O", XKB_KEY_kana_O }, - { "kana_openingbracket", XKB_KEY_kana_openingbracket }, - { "kana_RA", XKB_KEY_kana_RA }, - { "kana_RE", XKB_KEY_kana_RE }, - { "kana_RI", XKB_KEY_kana_RI }, - { "kana_RO", XKB_KEY_kana_RO }, - { "kana_RU", XKB_KEY_kana_RU }, - { "kana_SA", XKB_KEY_kana_SA }, - { "kana_SE", XKB_KEY_kana_SE }, - { "kana_SHI", XKB_KEY_kana_SHI }, - { "Kana_Shift", XKB_KEY_Kana_Shift }, - { "kana_SO", XKB_KEY_kana_SO }, - { "kana_SU", XKB_KEY_kana_SU }, - { "kana_switch", XKB_KEY_kana_switch }, - { "kana_TA", XKB_KEY_kana_TA }, - { "kana_TE", XKB_KEY_kana_TE }, - { "kana_TI", XKB_KEY_kana_TI }, - { "kana_TO", XKB_KEY_kana_TO }, - { "kana_tsu", XKB_KEY_kana_tsu }, - { "kana_TSU", XKB_KEY_kana_TSU }, - { "kana_tu", XKB_KEY_kana_tu }, - { "kana_TU", XKB_KEY_kana_TU }, - { "kana_u", XKB_KEY_kana_u }, - { "kana_U", XKB_KEY_kana_U }, - { "kana_WA", XKB_KEY_kana_WA }, - { "kana_WO", XKB_KEY_kana_WO }, - { "kana_ya", XKB_KEY_kana_ya }, - { "kana_YA", XKB_KEY_kana_YA }, - { "kana_yo", XKB_KEY_kana_yo }, - { "kana_YO", XKB_KEY_kana_YO }, - { "kana_yu", XKB_KEY_kana_yu }, - { "kana_YU", XKB_KEY_kana_YU }, - { "Kanji", XKB_KEY_Kanji }, - { "Kanji_Bangou", XKB_KEY_Kanji_Bangou }, - { "kappa", XKB_KEY_kappa }, - { "Katakana", XKB_KEY_Katakana }, - { "Kcedilla", XKB_KEY_Kcedilla }, - { "kcedilla", XKB_KEY_kcedilla }, - { "Korean_Won", XKB_KEY_Korean_Won }, - { "KP_0", XKB_KEY_KP_0 }, - { "KP_1", XKB_KEY_KP_1 }, - { "KP_2", XKB_KEY_KP_2 }, - { "KP_3", XKB_KEY_KP_3 }, - { "KP_4", XKB_KEY_KP_4 }, - { "KP_5", XKB_KEY_KP_5 }, - { "KP_6", XKB_KEY_KP_6 }, - { "KP_7", XKB_KEY_KP_7 }, - { "KP_8", XKB_KEY_KP_8 }, - { "KP_9", XKB_KEY_KP_9 }, - { "KP_Add", XKB_KEY_KP_Add }, - { "KP_BackTab", XKB_KEY_KP_BackTab }, - { "KP_Begin", XKB_KEY_KP_Begin }, - { "KP_Decimal", XKB_KEY_KP_Decimal }, - { "KP_Delete", XKB_KEY_KP_Delete }, - { "KP_Divide", XKB_KEY_KP_Divide }, - { "KP_Down", XKB_KEY_KP_Down }, - { "KP_End", XKB_KEY_KP_End }, - { "KP_Enter", XKB_KEY_KP_Enter }, - { "KP_Equal", XKB_KEY_KP_Equal }, - { "KP_F1", XKB_KEY_KP_F1 }, - { "KP_F2", XKB_KEY_KP_F2 }, - { "KP_F3", XKB_KEY_KP_F3 }, - { "KP_F4", XKB_KEY_KP_F4 }, - { "KP_Home", XKB_KEY_KP_Home }, - { "KP_Insert", XKB_KEY_KP_Insert }, - { "KP_Left", XKB_KEY_KP_Left }, - { "KP_Multiply", XKB_KEY_KP_Multiply }, - { "KP_Next", XKB_KEY_KP_Next }, - { "KP_Page_Down", XKB_KEY_KP_Page_Down }, - { "KP_Page_Up", XKB_KEY_KP_Page_Up }, - { "KP_Prior", XKB_KEY_KP_Prior }, - { "KP_Right", XKB_KEY_KP_Right }, - { "KP_Separator", XKB_KEY_KP_Separator }, - { "KP_Space", XKB_KEY_KP_Space }, - { "KP_Subtract", XKB_KEY_KP_Subtract }, - { "KP_Tab", XKB_KEY_KP_Tab }, - { "KP_Up", XKB_KEY_KP_Up }, - { "kra", XKB_KEY_kra }, - { "L", XKB_KEY_L }, - { "l", XKB_KEY_l }, - { "L1", XKB_KEY_L1 }, - { "L10", XKB_KEY_L10 }, - { "L2", XKB_KEY_L2 }, - { "L3", XKB_KEY_L3 }, - { "L4", XKB_KEY_L4 }, - { "L5", XKB_KEY_L5 }, - { "L6", XKB_KEY_L6 }, - { "L7", XKB_KEY_L7 }, - { "L8", XKB_KEY_L8 }, - { "L9", XKB_KEY_L9 }, - { "Lacute", XKB_KEY_Lacute }, - { "lacute", XKB_KEY_lacute }, - { "Last_Virtual_Screen", XKB_KEY_Last_Virtual_Screen }, - { "latincross", XKB_KEY_latincross }, - { "Lbelowdot", XKB_KEY_Lbelowdot }, - { "lbelowdot", XKB_KEY_lbelowdot }, - { "Lcaron", XKB_KEY_Lcaron }, - { "lcaron", XKB_KEY_lcaron }, - { "Lcedilla", XKB_KEY_Lcedilla }, - { "lcedilla", XKB_KEY_lcedilla }, - { "Left", XKB_KEY_Left }, - { "leftanglebracket", XKB_KEY_leftanglebracket }, - { "leftarrow", XKB_KEY_leftarrow }, - { "leftcaret", XKB_KEY_leftcaret }, - { "leftdoublequotemark", XKB_KEY_leftdoublequotemark }, - { "leftmiddlecurlybrace", XKB_KEY_leftmiddlecurlybrace }, - { "leftopentriangle", XKB_KEY_leftopentriangle }, - { "leftpointer", XKB_KEY_leftpointer }, - { "leftradical", XKB_KEY_leftradical }, - { "leftshoe", XKB_KEY_leftshoe }, - { "leftsinglequotemark", XKB_KEY_leftsinglequotemark }, - { "leftt", XKB_KEY_leftt }, - { "lefttack", XKB_KEY_lefttack }, - { "less", XKB_KEY_less }, - { "lessthanequal", XKB_KEY_lessthanequal }, - { "lf", XKB_KEY_lf }, - { "Linefeed", XKB_KEY_Linefeed }, - { "lira", XKB_KEY_lira }, - { "LiraSign", XKB_KEY_LiraSign }, - { "logicaland", XKB_KEY_logicaland }, - { "logicalor", XKB_KEY_logicalor }, - { "longminus", XKB_KEY_longminus }, - { "lowleftcorner", XKB_KEY_lowleftcorner }, - { "lowrightcorner", XKB_KEY_lowrightcorner }, - { "Lstroke", XKB_KEY_Lstroke }, - { "lstroke", XKB_KEY_lstroke }, - { "M", XKB_KEY_M }, - { "m", XKB_KEY_m }, - { "Mabovedot", XKB_KEY_Mabovedot }, - { "mabovedot", XKB_KEY_mabovedot }, - { "Macedonia_dse", XKB_KEY_Macedonia_dse }, - { "Macedonia_DSE", XKB_KEY_Macedonia_DSE }, - { "Macedonia_gje", XKB_KEY_Macedonia_gje }, - { "Macedonia_GJE", XKB_KEY_Macedonia_GJE }, - { "Macedonia_kje", XKB_KEY_Macedonia_kje }, - { "Macedonia_KJE", XKB_KEY_Macedonia_KJE }, - { "macron", XKB_KEY_macron }, - { "Mae_Koho", XKB_KEY_Mae_Koho }, - { "malesymbol", XKB_KEY_malesymbol }, - { "maltesecross", XKB_KEY_maltesecross }, - { "marker", XKB_KEY_marker }, - { "masculine", XKB_KEY_masculine }, - { "Massyo", XKB_KEY_Massyo }, - { "Menu", XKB_KEY_Menu }, - { "Meta_L", XKB_KEY_Meta_L }, - { "Meta_R", XKB_KEY_Meta_R }, - { "MillSign", XKB_KEY_MillSign }, - { "minus", XKB_KEY_minus }, - { "minutes", XKB_KEY_minutes }, - { "Mode_switch", XKB_KEY_Mode_switch }, - { "MouseKeys_Accel_Enable", XKB_KEY_MouseKeys_Accel_Enable }, - { "MouseKeys_Enable", XKB_KEY_MouseKeys_Enable }, - { "mu", XKB_KEY_mu }, - { "Muhenkan", XKB_KEY_Muhenkan }, - { "Multi_key", XKB_KEY_Multi_key }, - { "MultipleCandidate", XKB_KEY_MultipleCandidate }, - { "multiply", XKB_KEY_multiply }, - { "musicalflat", XKB_KEY_musicalflat }, - { "musicalsharp", XKB_KEY_musicalsharp }, - { "mute_acute", XKB_KEY_mute_acute }, - { "mute_asciicircum", XKB_KEY_mute_asciicircum }, - { "mute_asciitilde", XKB_KEY_mute_asciitilde }, - { "mute_diaeresis", XKB_KEY_mute_diaeresis }, - { "mute_grave", XKB_KEY_mute_grave }, - { "N", XKB_KEY_N }, - { "n", XKB_KEY_n }, - { "nabla", XKB_KEY_nabla }, - { "Nacute", XKB_KEY_Nacute }, - { "nacute", XKB_KEY_nacute }, - { "NairaSign", XKB_KEY_NairaSign }, - { "Ncaron", XKB_KEY_Ncaron }, - { "ncaron", XKB_KEY_ncaron }, - { "Ncedilla", XKB_KEY_Ncedilla }, - { "ncedilla", XKB_KEY_ncedilla }, - { "NewSheqelSign", XKB_KEY_NewSheqelSign }, - { "Next", XKB_KEY_Next }, - { "Next_Virtual_Screen", XKB_KEY_Next_Virtual_Screen }, - { "ninesubscript", XKB_KEY_ninesubscript }, - { "ninesuperior", XKB_KEY_ninesuperior }, - { "nl", XKB_KEY_nl }, - { "nobreakspace", XKB_KEY_nobreakspace }, - { "NoSymbol", XKB_KEY_NoSymbol }, - { "notapproxeq", XKB_KEY_notapproxeq }, - { "notelementof", XKB_KEY_notelementof }, - { "notequal", XKB_KEY_notequal }, - { "notidentical", XKB_KEY_notidentical }, - { "notsign", XKB_KEY_notsign }, - { "Ntilde", XKB_KEY_Ntilde }, - { "ntilde", XKB_KEY_ntilde }, - { "Num_Lock", XKB_KEY_Num_Lock }, - { "numbersign", XKB_KEY_numbersign }, - { "numerosign", XKB_KEY_numerosign }, - { "O", XKB_KEY_O }, - { "o", XKB_KEY_o }, - { "Oacute", XKB_KEY_Oacute }, - { "oacute", XKB_KEY_oacute }, - { "Obarred", XKB_KEY_Obarred }, - { "obarred", XKB_KEY_obarred }, - { "Obelowdot", XKB_KEY_Obelowdot }, - { "obelowdot", XKB_KEY_obelowdot }, - { "Ocaron", XKB_KEY_Ocaron }, - { "ocaron", XKB_KEY_ocaron }, - { "Ocircumflex", XKB_KEY_Ocircumflex }, - { "ocircumflex", XKB_KEY_ocircumflex }, - { "Ocircumflexacute", XKB_KEY_Ocircumflexacute }, - { "ocircumflexacute", XKB_KEY_ocircumflexacute }, - { "Ocircumflexbelowdot", XKB_KEY_Ocircumflexbelowdot }, - { "ocircumflexbelowdot", XKB_KEY_ocircumflexbelowdot }, - { "Ocircumflexgrave", XKB_KEY_Ocircumflexgrave }, - { "ocircumflexgrave", XKB_KEY_ocircumflexgrave }, - { "Ocircumflexhook", XKB_KEY_Ocircumflexhook }, - { "ocircumflexhook", XKB_KEY_ocircumflexhook }, - { "Ocircumflextilde", XKB_KEY_Ocircumflextilde }, - { "ocircumflextilde", XKB_KEY_ocircumflextilde }, - { "Odiaeresis", XKB_KEY_Odiaeresis }, - { "odiaeresis", XKB_KEY_odiaeresis }, - { "Odoubleacute", XKB_KEY_Odoubleacute }, - { "odoubleacute", XKB_KEY_odoubleacute }, - { "OE", XKB_KEY_OE }, - { "oe", XKB_KEY_oe }, - { "ogonek", XKB_KEY_ogonek }, - { "Ograve", XKB_KEY_Ograve }, - { "ograve", XKB_KEY_ograve }, - { "Ohook", XKB_KEY_Ohook }, - { "ohook", XKB_KEY_ohook }, - { "Ohorn", XKB_KEY_Ohorn }, - { "ohorn", XKB_KEY_ohorn }, - { "Ohornacute", XKB_KEY_Ohornacute }, - { "ohornacute", XKB_KEY_ohornacute }, - { "Ohornbelowdot", XKB_KEY_Ohornbelowdot }, - { "ohornbelowdot", XKB_KEY_ohornbelowdot }, - { "Ohorngrave", XKB_KEY_Ohorngrave }, - { "ohorngrave", XKB_KEY_ohorngrave }, - { "Ohornhook", XKB_KEY_Ohornhook }, - { "ohornhook", XKB_KEY_ohornhook }, - { "Ohorntilde", XKB_KEY_Ohorntilde }, - { "ohorntilde", XKB_KEY_ohorntilde }, - { "Omacron", XKB_KEY_Omacron }, - { "omacron", XKB_KEY_omacron }, - { "oneeighth", XKB_KEY_oneeighth }, - { "onefifth", XKB_KEY_onefifth }, - { "onehalf", XKB_KEY_onehalf }, - { "onequarter", XKB_KEY_onequarter }, - { "onesixth", XKB_KEY_onesixth }, - { "onesubscript", XKB_KEY_onesubscript }, - { "onesuperior", XKB_KEY_onesuperior }, - { "onethird", XKB_KEY_onethird }, - { "Ooblique", XKB_KEY_Ooblique }, - { "ooblique", XKB_KEY_ooblique }, - { "openrectbullet", XKB_KEY_openrectbullet }, - { "openstar", XKB_KEY_openstar }, - { "opentribulletdown", XKB_KEY_opentribulletdown }, - { "opentribulletup", XKB_KEY_opentribulletup }, - { "ordfeminine", XKB_KEY_ordfeminine }, - { "osfActivate", XKB_KEY_osfActivate }, - { "osfAddMode", XKB_KEY_osfAddMode }, - { "osfBackSpace", XKB_KEY_osfBackSpace }, - { "osfBackTab", XKB_KEY_osfBackTab }, - { "osfBeginData", XKB_KEY_osfBeginData }, - { "osfBeginLine", XKB_KEY_osfBeginLine }, - { "osfCancel", XKB_KEY_osfCancel }, - { "osfClear", XKB_KEY_osfClear }, - { "osfCopy", XKB_KEY_osfCopy }, - { "osfCut", XKB_KEY_osfCut }, - { "osfDelete", XKB_KEY_osfDelete }, - { "osfDeselectAll", XKB_KEY_osfDeselectAll }, - { "osfDown", XKB_KEY_osfDown }, - { "osfEndData", XKB_KEY_osfEndData }, - { "osfEndLine", XKB_KEY_osfEndLine }, - { "osfEscape", XKB_KEY_osfEscape }, - { "osfExtend", XKB_KEY_osfExtend }, - { "osfHelp", XKB_KEY_osfHelp }, - { "osfInsert", XKB_KEY_osfInsert }, - { "osfLeft", XKB_KEY_osfLeft }, - { "osfMenu", XKB_KEY_osfMenu }, - { "osfMenuBar", XKB_KEY_osfMenuBar }, - { "osfNextField", XKB_KEY_osfNextField }, - { "osfNextMenu", XKB_KEY_osfNextMenu }, - { "osfPageDown", XKB_KEY_osfPageDown }, - { "osfPageLeft", XKB_KEY_osfPageLeft }, - { "osfPageRight", XKB_KEY_osfPageRight }, - { "osfPageUp", XKB_KEY_osfPageUp }, - { "osfPaste", XKB_KEY_osfPaste }, - { "osfPrevField", XKB_KEY_osfPrevField }, - { "osfPrevMenu", XKB_KEY_osfPrevMenu }, - { "osfPrimaryPaste", XKB_KEY_osfPrimaryPaste }, - { "osfQuickPaste", XKB_KEY_osfQuickPaste }, - { "osfReselect", XKB_KEY_osfReselect }, - { "osfRestore", XKB_KEY_osfRestore }, - { "osfRight", XKB_KEY_osfRight }, - { "osfSelect", XKB_KEY_osfSelect }, - { "osfSelectAll", XKB_KEY_osfSelectAll }, - { "osfUndo", XKB_KEY_osfUndo }, - { "osfUp", XKB_KEY_osfUp }, - { "Oslash", XKB_KEY_Oslash }, - { "oslash", XKB_KEY_oslash }, - { "Otilde", XKB_KEY_Otilde }, - { "otilde", XKB_KEY_otilde }, - { "overbar", XKB_KEY_overbar }, - { "Overlay1_Enable", XKB_KEY_Overlay1_Enable }, - { "Overlay2_Enable", XKB_KEY_Overlay2_Enable }, - { "overline", XKB_KEY_overline }, - { "P", XKB_KEY_P }, - { "p", XKB_KEY_p }, - { "Pabovedot", XKB_KEY_Pabovedot }, - { "pabovedot", XKB_KEY_pabovedot }, - { "Page_Down", XKB_KEY_Page_Down }, - { "Page_Up", XKB_KEY_Page_Up }, - { "paragraph", XKB_KEY_paragraph }, - { "parenleft", XKB_KEY_parenleft }, - { "parenright", XKB_KEY_parenright }, - { "partdifferential", XKB_KEY_partdifferential }, - { "partialderivative", XKB_KEY_partialderivative }, - { "Pause", XKB_KEY_Pause }, - { "percent", XKB_KEY_percent }, - { "period", XKB_KEY_period }, - { "periodcentered", XKB_KEY_periodcentered }, - { "permille", XKB_KEY_permille }, - { "PesetaSign", XKB_KEY_PesetaSign }, - { "phonographcopyright", XKB_KEY_phonographcopyright }, - { "plus", XKB_KEY_plus }, - { "plusminus", XKB_KEY_plusminus }, - { "Pointer_Accelerate", XKB_KEY_Pointer_Accelerate }, - { "Pointer_Button1", XKB_KEY_Pointer_Button1 }, - { "Pointer_Button2", XKB_KEY_Pointer_Button2 }, - { "Pointer_Button3", XKB_KEY_Pointer_Button3 }, - { "Pointer_Button4", XKB_KEY_Pointer_Button4 }, - { "Pointer_Button5", XKB_KEY_Pointer_Button5 }, - { "Pointer_Button_Dflt", XKB_KEY_Pointer_Button_Dflt }, - { "Pointer_DblClick1", XKB_KEY_Pointer_DblClick1 }, - { "Pointer_DblClick2", XKB_KEY_Pointer_DblClick2 }, - { "Pointer_DblClick3", XKB_KEY_Pointer_DblClick3 }, - { "Pointer_DblClick4", XKB_KEY_Pointer_DblClick4 }, - { "Pointer_DblClick5", XKB_KEY_Pointer_DblClick5 }, - { "Pointer_DblClick_Dflt", XKB_KEY_Pointer_DblClick_Dflt }, - { "Pointer_DfltBtnNext", XKB_KEY_Pointer_DfltBtnNext }, - { "Pointer_DfltBtnPrev", XKB_KEY_Pointer_DfltBtnPrev }, - { "Pointer_Down", XKB_KEY_Pointer_Down }, - { "Pointer_DownLeft", XKB_KEY_Pointer_DownLeft }, - { "Pointer_DownRight", XKB_KEY_Pointer_DownRight }, - { "Pointer_Drag1", XKB_KEY_Pointer_Drag1 }, - { "Pointer_Drag2", XKB_KEY_Pointer_Drag2 }, - { "Pointer_Drag3", XKB_KEY_Pointer_Drag3 }, - { "Pointer_Drag4", XKB_KEY_Pointer_Drag4 }, - { "Pointer_Drag5", XKB_KEY_Pointer_Drag5 }, - { "Pointer_Drag_Dflt", XKB_KEY_Pointer_Drag_Dflt }, - { "Pointer_EnableKeys", XKB_KEY_Pointer_EnableKeys }, - { "Pointer_Left", XKB_KEY_Pointer_Left }, - { "Pointer_Right", XKB_KEY_Pointer_Right }, - { "Pointer_Up", XKB_KEY_Pointer_Up }, - { "Pointer_UpLeft", XKB_KEY_Pointer_UpLeft }, - { "Pointer_UpRight", XKB_KEY_Pointer_UpRight }, - { "prescription", XKB_KEY_prescription }, - { "Prev_Virtual_Screen", XKB_KEY_Prev_Virtual_Screen }, - { "PreviousCandidate", XKB_KEY_PreviousCandidate }, - { "Print", XKB_KEY_Print }, - { "Prior", XKB_KEY_Prior }, - { "prolongedsound", XKB_KEY_prolongedsound }, - { "punctspace", XKB_KEY_punctspace }, - { "Q", XKB_KEY_Q }, - { "q", XKB_KEY_q }, - { "quad", XKB_KEY_quad }, - { "question", XKB_KEY_question }, - { "questiondown", XKB_KEY_questiondown }, - { "quotedbl", XKB_KEY_quotedbl }, - { "quoteleft", XKB_KEY_quoteleft }, - { "quoteright", XKB_KEY_quoteright }, - { "R", XKB_KEY_R }, - { "r", XKB_KEY_r }, - { "R1", XKB_KEY_R1 }, - { "R10", XKB_KEY_R10 }, - { "R11", XKB_KEY_R11 }, - { "R12", XKB_KEY_R12 }, - { "R13", XKB_KEY_R13 }, - { "R14", XKB_KEY_R14 }, - { "R15", XKB_KEY_R15 }, - { "R2", XKB_KEY_R2 }, - { "R3", XKB_KEY_R3 }, - { "R4", XKB_KEY_R4 }, - { "R5", XKB_KEY_R5 }, - { "R6", XKB_KEY_R6 }, - { "R7", XKB_KEY_R7 }, - { "R8", XKB_KEY_R8 }, - { "R9", XKB_KEY_R9 }, - { "Racute", XKB_KEY_Racute }, - { "racute", XKB_KEY_racute }, - { "radical", XKB_KEY_radical }, - { "Rcaron", XKB_KEY_Rcaron }, - { "rcaron", XKB_KEY_rcaron }, - { "Rcedilla", XKB_KEY_Rcedilla }, - { "rcedilla", XKB_KEY_rcedilla }, - { "Redo", XKB_KEY_Redo }, - { "registered", XKB_KEY_registered }, - { "RepeatKeys_Enable", XKB_KEY_RepeatKeys_Enable }, - { "Reset", XKB_KEY_Reset }, - { "Return", XKB_KEY_Return }, - { "Right", XKB_KEY_Right }, - { "rightanglebracket", XKB_KEY_rightanglebracket }, - { "rightarrow", XKB_KEY_rightarrow }, - { "rightcaret", XKB_KEY_rightcaret }, - { "rightdoublequotemark", XKB_KEY_rightdoublequotemark }, - { "rightmiddlecurlybrace", XKB_KEY_rightmiddlecurlybrace }, - { "rightmiddlesummation", XKB_KEY_rightmiddlesummation }, - { "rightopentriangle", XKB_KEY_rightopentriangle }, - { "rightpointer", XKB_KEY_rightpointer }, - { "rightshoe", XKB_KEY_rightshoe }, - { "rightsinglequotemark", XKB_KEY_rightsinglequotemark }, - { "rightt", XKB_KEY_rightt }, - { "righttack", XKB_KEY_righttack }, - { "Romaji", XKB_KEY_Romaji }, - { "RupeeSign", XKB_KEY_RupeeSign }, - { "S", XKB_KEY_S }, - { "s", XKB_KEY_s }, - { "Sabovedot", XKB_KEY_Sabovedot }, - { "sabovedot", XKB_KEY_sabovedot }, - { "Sacute", XKB_KEY_Sacute }, - { "sacute", XKB_KEY_sacute }, - { "Scaron", XKB_KEY_Scaron }, - { "scaron", XKB_KEY_scaron }, - { "Scedilla", XKB_KEY_Scedilla }, - { "scedilla", XKB_KEY_scedilla }, - { "SCHWA", XKB_KEY_SCHWA }, - { "schwa", XKB_KEY_schwa }, - { "Scircumflex", XKB_KEY_Scircumflex }, - { "scircumflex", XKB_KEY_scircumflex }, - { "script_switch", XKB_KEY_script_switch }, - { "Scroll_Lock", XKB_KEY_Scroll_Lock }, - { "seconds", XKB_KEY_seconds }, - { "section", XKB_KEY_section }, - { "Select", XKB_KEY_Select }, - { "semicolon", XKB_KEY_semicolon }, - { "semivoicedsound", XKB_KEY_semivoicedsound }, - { "Serbian_dje", XKB_KEY_Serbian_dje }, - { "Serbian_DJE", XKB_KEY_Serbian_DJE }, - { "Serbian_dze", XKB_KEY_Serbian_dze }, - { "Serbian_DZE", XKB_KEY_Serbian_DZE }, - { "Serbian_je", XKB_KEY_Serbian_je }, - { "Serbian_JE", XKB_KEY_Serbian_JE }, - { "Serbian_lje", XKB_KEY_Serbian_lje }, - { "Serbian_LJE", XKB_KEY_Serbian_LJE }, - { "Serbian_nje", XKB_KEY_Serbian_nje }, - { "Serbian_NJE", XKB_KEY_Serbian_NJE }, - { "Serbian_tshe", XKB_KEY_Serbian_tshe }, - { "Serbian_TSHE", XKB_KEY_Serbian_TSHE }, - { "seveneighths", XKB_KEY_seveneighths }, - { "sevensubscript", XKB_KEY_sevensubscript }, - { "sevensuperior", XKB_KEY_sevensuperior }, - { "Shift_L", XKB_KEY_Shift_L }, - { "Shift_Lock", XKB_KEY_Shift_Lock }, - { "Shift_R", XKB_KEY_Shift_R }, - { "signaturemark", XKB_KEY_signaturemark }, - { "signifblank", XKB_KEY_signifblank }, - { "similarequal", XKB_KEY_similarequal }, - { "SingleCandidate", XKB_KEY_SingleCandidate }, - { "singlelowquotemark", XKB_KEY_singlelowquotemark }, - { "Sinh_a", XKB_KEY_Sinh_a }, - { "Sinh_aa", XKB_KEY_Sinh_aa }, - { "Sinh_aa2", XKB_KEY_Sinh_aa2 }, - { "Sinh_ae", XKB_KEY_Sinh_ae }, - { "Sinh_ae2", XKB_KEY_Sinh_ae2 }, - { "Sinh_aee", XKB_KEY_Sinh_aee }, - { "Sinh_aee2", XKB_KEY_Sinh_aee2 }, - { "Sinh_ai", XKB_KEY_Sinh_ai }, - { "Sinh_ai2", XKB_KEY_Sinh_ai2 }, - { "Sinh_al", XKB_KEY_Sinh_al }, - { "Sinh_au", XKB_KEY_Sinh_au }, - { "Sinh_au2", XKB_KEY_Sinh_au2 }, - { "Sinh_ba", XKB_KEY_Sinh_ba }, - { "Sinh_bha", XKB_KEY_Sinh_bha }, - { "Sinh_ca", XKB_KEY_Sinh_ca }, - { "Sinh_cha", XKB_KEY_Sinh_cha }, - { "Sinh_dda", XKB_KEY_Sinh_dda }, - { "Sinh_ddha", XKB_KEY_Sinh_ddha }, - { "Sinh_dha", XKB_KEY_Sinh_dha }, - { "Sinh_dhha", XKB_KEY_Sinh_dhha }, - { "Sinh_e", XKB_KEY_Sinh_e }, - { "Sinh_e2", XKB_KEY_Sinh_e2 }, - { "Sinh_ee", XKB_KEY_Sinh_ee }, - { "Sinh_ee2", XKB_KEY_Sinh_ee2 }, - { "Sinh_fa", XKB_KEY_Sinh_fa }, - { "Sinh_ga", XKB_KEY_Sinh_ga }, - { "Sinh_gha", XKB_KEY_Sinh_gha }, - { "Sinh_h2", XKB_KEY_Sinh_h2 }, - { "Sinh_ha", XKB_KEY_Sinh_ha }, - { "Sinh_i", XKB_KEY_Sinh_i }, - { "Sinh_i2", XKB_KEY_Sinh_i2 }, - { "Sinh_ii", XKB_KEY_Sinh_ii }, - { "Sinh_ii2", XKB_KEY_Sinh_ii2 }, - { "Sinh_ja", XKB_KEY_Sinh_ja }, - { "Sinh_jha", XKB_KEY_Sinh_jha }, - { "Sinh_jnya", XKB_KEY_Sinh_jnya }, - { "Sinh_ka", XKB_KEY_Sinh_ka }, - { "Sinh_kha", XKB_KEY_Sinh_kha }, - { "Sinh_kunddaliya", XKB_KEY_Sinh_kunddaliya }, - { "Sinh_la", XKB_KEY_Sinh_la }, - { "Sinh_lla", XKB_KEY_Sinh_lla }, - { "Sinh_lu", XKB_KEY_Sinh_lu }, - { "Sinh_lu2", XKB_KEY_Sinh_lu2 }, - { "Sinh_luu", XKB_KEY_Sinh_luu }, - { "Sinh_luu2", XKB_KEY_Sinh_luu2 }, - { "Sinh_ma", XKB_KEY_Sinh_ma }, - { "Sinh_mba", XKB_KEY_Sinh_mba }, - { "Sinh_na", XKB_KEY_Sinh_na }, - { "Sinh_ndda", XKB_KEY_Sinh_ndda }, - { "Sinh_ndha", XKB_KEY_Sinh_ndha }, - { "Sinh_ng", XKB_KEY_Sinh_ng }, - { "Sinh_ng2", XKB_KEY_Sinh_ng2 }, - { "Sinh_nga", XKB_KEY_Sinh_nga }, - { "Sinh_nja", XKB_KEY_Sinh_nja }, - { "Sinh_nna", XKB_KEY_Sinh_nna }, - { "Sinh_nya", XKB_KEY_Sinh_nya }, - { "Sinh_o", XKB_KEY_Sinh_o }, - { "Sinh_o2", XKB_KEY_Sinh_o2 }, - { "Sinh_oo", XKB_KEY_Sinh_oo }, - { "Sinh_oo2", XKB_KEY_Sinh_oo2 }, - { "Sinh_pa", XKB_KEY_Sinh_pa }, - { "Sinh_pha", XKB_KEY_Sinh_pha }, - { "Sinh_ra", XKB_KEY_Sinh_ra }, - { "Sinh_ri", XKB_KEY_Sinh_ri }, - { "Sinh_rii", XKB_KEY_Sinh_rii }, - { "Sinh_ru2", XKB_KEY_Sinh_ru2 }, - { "Sinh_ruu2", XKB_KEY_Sinh_ruu2 }, - { "Sinh_sa", XKB_KEY_Sinh_sa }, - { "Sinh_sha", XKB_KEY_Sinh_sha }, - { "Sinh_ssha", XKB_KEY_Sinh_ssha }, - { "Sinh_tha", XKB_KEY_Sinh_tha }, - { "Sinh_thha", XKB_KEY_Sinh_thha }, - { "Sinh_tta", XKB_KEY_Sinh_tta }, - { "Sinh_ttha", XKB_KEY_Sinh_ttha }, - { "Sinh_u", XKB_KEY_Sinh_u }, - { "Sinh_u2", XKB_KEY_Sinh_u2 }, - { "Sinh_uu", XKB_KEY_Sinh_uu }, - { "Sinh_uu2", XKB_KEY_Sinh_uu2 }, - { "Sinh_va", XKB_KEY_Sinh_va }, - { "Sinh_ya", XKB_KEY_Sinh_ya }, - { "sixsubscript", XKB_KEY_sixsubscript }, - { "sixsuperior", XKB_KEY_sixsuperior }, - { "slash", XKB_KEY_slash }, - { "SlowKeys_Enable", XKB_KEY_SlowKeys_Enable }, - { "soliddiamond", XKB_KEY_soliddiamond }, - { "space", XKB_KEY_space }, - { "squareroot", XKB_KEY_squareroot }, - { "ssharp", XKB_KEY_ssharp }, - { "sterling", XKB_KEY_sterling }, - { "StickyKeys_Enable", XKB_KEY_StickyKeys_Enable }, - { "stricteq", XKB_KEY_stricteq }, - { "SunAgain", XKB_KEY_SunAgain }, - { "SunAltGraph", XKB_KEY_SunAltGraph }, - { "SunAudioLowerVolume", XKB_KEY_SunAudioLowerVolume }, - { "SunAudioMute", XKB_KEY_SunAudioMute }, - { "SunAudioRaiseVolume", XKB_KEY_SunAudioRaiseVolume }, - { "SunCompose", XKB_KEY_SunCompose }, - { "SunCopy", XKB_KEY_SunCopy }, - { "SunCut", XKB_KEY_SunCut }, - { "SunF36", XKB_KEY_SunF36 }, - { "SunF37", XKB_KEY_SunF37 }, - { "SunFA_Acute", XKB_KEY_SunFA_Acute }, - { "SunFA_Cedilla", XKB_KEY_SunFA_Cedilla }, - { "SunFA_Circum", XKB_KEY_SunFA_Circum }, - { "SunFA_Diaeresis", XKB_KEY_SunFA_Diaeresis }, - { "SunFA_Grave", XKB_KEY_SunFA_Grave }, - { "SunFA_Tilde", XKB_KEY_SunFA_Tilde }, - { "SunFind", XKB_KEY_SunFind }, - { "SunFront", XKB_KEY_SunFront }, - { "SunOpen", XKB_KEY_SunOpen }, - { "SunPageDown", XKB_KEY_SunPageDown }, - { "SunPageUp", XKB_KEY_SunPageUp }, - { "SunPaste", XKB_KEY_SunPaste }, - { "SunPowerSwitch", XKB_KEY_SunPowerSwitch }, - { "SunPowerSwitchShift", XKB_KEY_SunPowerSwitchShift }, - { "SunPrint_Screen", XKB_KEY_SunPrint_Screen }, - { "SunProps", XKB_KEY_SunProps }, - { "SunStop", XKB_KEY_SunStop }, - { "SunSys_Req", XKB_KEY_SunSys_Req }, - { "SunUndo", XKB_KEY_SunUndo }, - { "SunVideoDegauss", XKB_KEY_SunVideoDegauss }, - { "SunVideoLowerBrightness", XKB_KEY_SunVideoLowerBrightness }, - { "SunVideoRaiseBrightness", XKB_KEY_SunVideoRaiseBrightness }, - { "Super_L", XKB_KEY_Super_L }, - { "Super_R", XKB_KEY_Super_R }, - { "Sys_Req", XKB_KEY_Sys_Req }, - { "System", XKB_KEY_System }, - { "T", XKB_KEY_T }, - { "t", XKB_KEY_t }, - { "Tab", XKB_KEY_Tab }, - { "Tabovedot", XKB_KEY_Tabovedot }, - { "tabovedot", XKB_KEY_tabovedot }, - { "Tcaron", XKB_KEY_Tcaron }, - { "tcaron", XKB_KEY_tcaron }, - { "Tcedilla", XKB_KEY_Tcedilla }, - { "tcedilla", XKB_KEY_tcedilla }, - { "telephone", XKB_KEY_telephone }, - { "telephonerecorder", XKB_KEY_telephonerecorder }, - { "Terminate_Server", XKB_KEY_Terminate_Server }, - { "Thai_baht", XKB_KEY_Thai_baht }, - { "Thai_bobaimai", XKB_KEY_Thai_bobaimai }, - { "Thai_chochan", XKB_KEY_Thai_chochan }, - { "Thai_chochang", XKB_KEY_Thai_chochang }, - { "Thai_choching", XKB_KEY_Thai_choching }, - { "Thai_chochoe", XKB_KEY_Thai_chochoe }, - { "Thai_dochada", XKB_KEY_Thai_dochada }, - { "Thai_dodek", XKB_KEY_Thai_dodek }, - { "Thai_fofa", XKB_KEY_Thai_fofa }, - { "Thai_fofan", XKB_KEY_Thai_fofan }, - { "Thai_hohip", XKB_KEY_Thai_hohip }, - { "Thai_honokhuk", XKB_KEY_Thai_honokhuk }, - { "Thai_khokhai", XKB_KEY_Thai_khokhai }, - { "Thai_khokhon", XKB_KEY_Thai_khokhon }, - { "Thai_khokhuat", XKB_KEY_Thai_khokhuat }, - { "Thai_khokhwai", XKB_KEY_Thai_khokhwai }, - { "Thai_khorakhang", XKB_KEY_Thai_khorakhang }, - { "Thai_kokai", XKB_KEY_Thai_kokai }, - { "Thai_lakkhangyao", XKB_KEY_Thai_lakkhangyao }, - { "Thai_lekchet", XKB_KEY_Thai_lekchet }, - { "Thai_lekha", XKB_KEY_Thai_lekha }, - { "Thai_lekhok", XKB_KEY_Thai_lekhok }, - { "Thai_lekkao", XKB_KEY_Thai_lekkao }, - { "Thai_leknung", XKB_KEY_Thai_leknung }, - { "Thai_lekpaet", XKB_KEY_Thai_lekpaet }, - { "Thai_leksam", XKB_KEY_Thai_leksam }, - { "Thai_leksi", XKB_KEY_Thai_leksi }, - { "Thai_leksong", XKB_KEY_Thai_leksong }, - { "Thai_leksun", XKB_KEY_Thai_leksun }, - { "Thai_lochula", XKB_KEY_Thai_lochula }, - { "Thai_loling", XKB_KEY_Thai_loling }, - { "Thai_lu", XKB_KEY_Thai_lu }, - { "Thai_maichattawa", XKB_KEY_Thai_maichattawa }, - { "Thai_maiek", XKB_KEY_Thai_maiek }, - { "Thai_maihanakat", XKB_KEY_Thai_maihanakat }, - { "Thai_maihanakat_maitho", XKB_KEY_Thai_maihanakat_maitho }, - { "Thai_maitaikhu", XKB_KEY_Thai_maitaikhu }, - { "Thai_maitho", XKB_KEY_Thai_maitho }, - { "Thai_maitri", XKB_KEY_Thai_maitri }, - { "Thai_maiyamok", XKB_KEY_Thai_maiyamok }, - { "Thai_moma", XKB_KEY_Thai_moma }, - { "Thai_ngongu", XKB_KEY_Thai_ngongu }, - { "Thai_nikhahit", XKB_KEY_Thai_nikhahit }, - { "Thai_nonen", XKB_KEY_Thai_nonen }, - { "Thai_nonu", XKB_KEY_Thai_nonu }, - { "Thai_oang", XKB_KEY_Thai_oang }, - { "Thai_paiyannoi", XKB_KEY_Thai_paiyannoi }, - { "Thai_phinthu", XKB_KEY_Thai_phinthu }, - { "Thai_phophan", XKB_KEY_Thai_phophan }, - { "Thai_phophung", XKB_KEY_Thai_phophung }, - { "Thai_phosamphao", XKB_KEY_Thai_phosamphao }, - { "Thai_popla", XKB_KEY_Thai_popla }, - { "Thai_rorua", XKB_KEY_Thai_rorua }, - { "Thai_ru", XKB_KEY_Thai_ru }, - { "Thai_saraa", XKB_KEY_Thai_saraa }, - { "Thai_saraaa", XKB_KEY_Thai_saraaa }, - { "Thai_saraae", XKB_KEY_Thai_saraae }, - { "Thai_saraaimaimalai", XKB_KEY_Thai_saraaimaimalai }, - { "Thai_saraaimaimuan", XKB_KEY_Thai_saraaimaimuan }, - { "Thai_saraam", XKB_KEY_Thai_saraam }, - { "Thai_sarae", XKB_KEY_Thai_sarae }, - { "Thai_sarai", XKB_KEY_Thai_sarai }, - { "Thai_saraii", XKB_KEY_Thai_saraii }, - { "Thai_sarao", XKB_KEY_Thai_sarao }, - { "Thai_sarau", XKB_KEY_Thai_sarau }, - { "Thai_saraue", XKB_KEY_Thai_saraue }, - { "Thai_sarauee", XKB_KEY_Thai_sarauee }, - { "Thai_sarauu", XKB_KEY_Thai_sarauu }, - { "Thai_sorusi", XKB_KEY_Thai_sorusi }, - { "Thai_sosala", XKB_KEY_Thai_sosala }, - { "Thai_soso", XKB_KEY_Thai_soso }, - { "Thai_sosua", XKB_KEY_Thai_sosua }, - { "Thai_thanthakhat", XKB_KEY_Thai_thanthakhat }, - { "Thai_thonangmontho", XKB_KEY_Thai_thonangmontho }, - { "Thai_thophuthao", XKB_KEY_Thai_thophuthao }, - { "Thai_thothahan", XKB_KEY_Thai_thothahan }, - { "Thai_thothan", XKB_KEY_Thai_thothan }, - { "Thai_thothong", XKB_KEY_Thai_thothong }, - { "Thai_thothung", XKB_KEY_Thai_thothung }, - { "Thai_topatak", XKB_KEY_Thai_topatak }, - { "Thai_totao", XKB_KEY_Thai_totao }, - { "Thai_wowaen", XKB_KEY_Thai_wowaen }, - { "Thai_yoyak", XKB_KEY_Thai_yoyak }, - { "Thai_yoying", XKB_KEY_Thai_yoying }, - { "therefore", XKB_KEY_therefore }, - { "thinspace", XKB_KEY_thinspace }, - { "THORN", XKB_KEY_THORN }, - { "Thorn", XKB_KEY_Thorn }, - { "thorn", XKB_KEY_thorn }, - { "threeeighths", XKB_KEY_threeeighths }, - { "threefifths", XKB_KEY_threefifths }, - { "threequarters", XKB_KEY_threequarters }, - { "threesubscript", XKB_KEY_threesubscript }, - { "threesuperior", XKB_KEY_threesuperior }, - { "tintegral", XKB_KEY_tintegral }, - { "topintegral", XKB_KEY_topintegral }, - { "topleftparens", XKB_KEY_topleftparens }, - { "topleftradical", XKB_KEY_topleftradical }, - { "topleftsqbracket", XKB_KEY_topleftsqbracket }, - { "topleftsummation", XKB_KEY_topleftsummation }, - { "toprightparens", XKB_KEY_toprightparens }, - { "toprightsqbracket", XKB_KEY_toprightsqbracket }, - { "toprightsummation", XKB_KEY_toprightsummation }, - { "topt", XKB_KEY_topt }, - { "topvertsummationconnector", XKB_KEY_topvertsummationconnector }, - { "Touroku", XKB_KEY_Touroku }, - { "trademark", XKB_KEY_trademark }, - { "trademarkincircle", XKB_KEY_trademarkincircle }, - { "Tslash", XKB_KEY_Tslash }, - { "tslash", XKB_KEY_tslash }, - { "twofifths", XKB_KEY_twofifths }, - { "twosubscript", XKB_KEY_twosubscript }, - { "twosuperior", XKB_KEY_twosuperior }, - { "twothirds", XKB_KEY_twothirds }, - { "U", XKB_KEY_U }, - { "u", XKB_KEY_u }, - { "Uacute", XKB_KEY_Uacute }, - { "uacute", XKB_KEY_uacute }, - { "Ubelowdot", XKB_KEY_Ubelowdot }, - { "ubelowdot", XKB_KEY_ubelowdot }, - { "Ubreve", XKB_KEY_Ubreve }, - { "ubreve", XKB_KEY_ubreve }, - { "Ucircumflex", XKB_KEY_Ucircumflex }, - { "ucircumflex", XKB_KEY_ucircumflex }, - { "Udiaeresis", XKB_KEY_Udiaeresis }, - { "udiaeresis", XKB_KEY_udiaeresis }, - { "Udoubleacute", XKB_KEY_Udoubleacute }, - { "udoubleacute", XKB_KEY_udoubleacute }, - { "Ugrave", XKB_KEY_Ugrave }, - { "ugrave", XKB_KEY_ugrave }, - { "Uhook", XKB_KEY_Uhook }, - { "uhook", XKB_KEY_uhook }, - { "Uhorn", XKB_KEY_Uhorn }, - { "uhorn", XKB_KEY_uhorn }, - { "Uhornacute", XKB_KEY_Uhornacute }, - { "uhornacute", XKB_KEY_uhornacute }, - { "Uhornbelowdot", XKB_KEY_Uhornbelowdot }, - { "uhornbelowdot", XKB_KEY_uhornbelowdot }, - { "Uhorngrave", XKB_KEY_Uhorngrave }, - { "uhorngrave", XKB_KEY_uhorngrave }, - { "Uhornhook", XKB_KEY_Uhornhook }, - { "uhornhook", XKB_KEY_uhornhook }, - { "Uhorntilde", XKB_KEY_Uhorntilde }, - { "uhorntilde", XKB_KEY_uhorntilde }, - { "Ukrainian_ghe_with_upturn", XKB_KEY_Ukrainian_ghe_with_upturn }, - { "Ukrainian_GHE_WITH_UPTURN", XKB_KEY_Ukrainian_GHE_WITH_UPTURN }, - { "Ukrainian_i", XKB_KEY_Ukrainian_i }, - { "Ukrainian_I", XKB_KEY_Ukrainian_I }, - { "Ukrainian_ie", XKB_KEY_Ukrainian_ie }, - { "Ukrainian_IE", XKB_KEY_Ukrainian_IE }, - { "Ukrainian_yi", XKB_KEY_Ukrainian_yi }, - { "Ukrainian_YI", XKB_KEY_Ukrainian_YI }, - { "Ukranian_i", XKB_KEY_Ukranian_i }, - { "Ukranian_I", XKB_KEY_Ukranian_I }, - { "Ukranian_je", XKB_KEY_Ukranian_je }, - { "Ukranian_JE", XKB_KEY_Ukranian_JE }, - { "Ukranian_yi", XKB_KEY_Ukranian_yi }, - { "Ukranian_YI", XKB_KEY_Ukranian_YI }, - { "Umacron", XKB_KEY_Umacron }, - { "umacron", XKB_KEY_umacron }, - { "underbar", XKB_KEY_underbar }, - { "underscore", XKB_KEY_underscore }, - { "Undo", XKB_KEY_Undo }, - { "union", XKB_KEY_union }, - { "Uogonek", XKB_KEY_Uogonek }, - { "uogonek", XKB_KEY_uogonek }, - { "Up", XKB_KEY_Up }, - { "uparrow", XKB_KEY_uparrow }, - { "upcaret", XKB_KEY_upcaret }, - { "upleftcorner", XKB_KEY_upleftcorner }, - { "uprightcorner", XKB_KEY_uprightcorner }, - { "upshoe", XKB_KEY_upshoe }, - { "upstile", XKB_KEY_upstile }, - { "uptack", XKB_KEY_uptack }, - { "Uring", XKB_KEY_Uring }, - { "uring", XKB_KEY_uring }, - { "User", XKB_KEY_User }, - { "Utilde", XKB_KEY_Utilde }, - { "utilde", XKB_KEY_utilde }, - { "V", XKB_KEY_V }, - { "v", XKB_KEY_v }, - { "variation", XKB_KEY_variation }, - { "vertbar", XKB_KEY_vertbar }, - { "vertconnector", XKB_KEY_vertconnector }, - { "voicedsound", XKB_KEY_voicedsound }, - { "VoidSymbol", XKB_KEY_VoidSymbol }, - { "vt", XKB_KEY_vt }, - { "W", XKB_KEY_W }, - { "w", XKB_KEY_w }, - { "Wacute", XKB_KEY_Wacute }, - { "wacute", XKB_KEY_wacute }, - { "Wcircumflex", XKB_KEY_Wcircumflex }, - { "wcircumflex", XKB_KEY_wcircumflex }, - { "Wdiaeresis", XKB_KEY_Wdiaeresis }, - { "wdiaeresis", XKB_KEY_wdiaeresis }, - { "Wgrave", XKB_KEY_Wgrave }, - { "wgrave", XKB_KEY_wgrave }, - { "WonSign", XKB_KEY_WonSign }, - { "X", XKB_KEY_X }, - { "x", XKB_KEY_x }, - { "Xabovedot", XKB_KEY_Xabovedot }, - { "xabovedot", XKB_KEY_xabovedot }, - { "XF86AddFavorite", XKB_KEY_XF86AddFavorite }, - { "XF86ApplicationLeft", XKB_KEY_XF86ApplicationLeft }, - { "XF86ApplicationRight", XKB_KEY_XF86ApplicationRight }, - { "XF86AudioCycleTrack", XKB_KEY_XF86AudioCycleTrack }, - { "XF86AudioForward", XKB_KEY_XF86AudioForward }, - { "XF86AudioLowerVolume", XKB_KEY_XF86AudioLowerVolume }, - { "XF86AudioMedia", XKB_KEY_XF86AudioMedia }, - { "XF86AudioMute", XKB_KEY_XF86AudioMute }, - { "XF86AudioNext", XKB_KEY_XF86AudioNext }, - { "XF86AudioPause", XKB_KEY_XF86AudioPause }, - { "XF86AudioPlay", XKB_KEY_XF86AudioPlay }, - { "XF86AudioPrev", XKB_KEY_XF86AudioPrev }, - { "XF86AudioRaiseVolume", XKB_KEY_XF86AudioRaiseVolume }, - { "XF86AudioRandomPlay", XKB_KEY_XF86AudioRandomPlay }, - { "XF86AudioRecord", XKB_KEY_XF86AudioRecord }, - { "XF86AudioRepeat", XKB_KEY_XF86AudioRepeat }, - { "XF86AudioRewind", XKB_KEY_XF86AudioRewind }, - { "XF86AudioStop", XKB_KEY_XF86AudioStop }, - { "XF86Away", XKB_KEY_XF86Away }, - { "XF86Back", XKB_KEY_XF86Back }, - { "XF86BackForward", XKB_KEY_XF86BackForward }, - { "XF86Battery", XKB_KEY_XF86Battery }, - { "XF86Blue", XKB_KEY_XF86Blue }, - { "XF86Bluetooth", XKB_KEY_XF86Bluetooth }, - { "XF86Book", XKB_KEY_XF86Book }, - { "XF86BrightnessAdjust", XKB_KEY_XF86BrightnessAdjust }, - { "XF86Calculater", XKB_KEY_XF86Calculater }, - { "XF86Calculator", XKB_KEY_XF86Calculator }, - { "XF86Calendar", XKB_KEY_XF86Calendar }, - { "XF86CD", XKB_KEY_XF86CD }, - { "XF86Clear", XKB_KEY_XF86Clear }, - { "XF86ClearGrab", XKB_KEY_XF86ClearGrab }, - { "XF86Close", XKB_KEY_XF86Close }, - { "XF86Community", XKB_KEY_XF86Community }, - { "XF86ContrastAdjust", XKB_KEY_XF86ContrastAdjust }, - { "XF86Copy", XKB_KEY_XF86Copy }, - { "XF86Cut", XKB_KEY_XF86Cut }, - { "XF86CycleAngle", XKB_KEY_XF86CycleAngle }, - { "XF86Display", XKB_KEY_XF86Display }, - { "XF86Documents", XKB_KEY_XF86Documents }, - { "XF86DOS", XKB_KEY_XF86DOS }, - { "XF86Eject", XKB_KEY_XF86Eject }, - { "XF86Excel", XKB_KEY_XF86Excel }, - { "XF86Explorer", XKB_KEY_XF86Explorer }, - { "XF86Favorites", XKB_KEY_XF86Favorites }, - { "XF86Finance", XKB_KEY_XF86Finance }, - { "XF86Forward", XKB_KEY_XF86Forward }, - { "XF86FrameBack", XKB_KEY_XF86FrameBack }, - { "XF86FrameForward", XKB_KEY_XF86FrameForward }, - { "XF86Game", XKB_KEY_XF86Game }, - { "XF86Go", XKB_KEY_XF86Go }, - { "XF86Green", XKB_KEY_XF86Green }, - { "XF86Hibernate", XKB_KEY_XF86Hibernate }, - { "XF86History", XKB_KEY_XF86History }, - { "XF86HomePage", XKB_KEY_XF86HomePage }, - { "XF86HotLinks", XKB_KEY_XF86HotLinks }, - { "XF86iTouch", XKB_KEY_XF86iTouch }, - { "XF86KbdBrightnessDown", XKB_KEY_XF86KbdBrightnessDown }, - { "XF86KbdBrightnessUp", XKB_KEY_XF86KbdBrightnessUp }, - { "XF86KbdLightOnOff", XKB_KEY_XF86KbdLightOnOff }, - { "XF86Launch0", XKB_KEY_XF86Launch0 }, - { "XF86Launch1", XKB_KEY_XF86Launch1 }, - { "XF86Launch2", XKB_KEY_XF86Launch2 }, - { "XF86Launch3", XKB_KEY_XF86Launch3 }, - { "XF86Launch4", XKB_KEY_XF86Launch4 }, - { "XF86Launch5", XKB_KEY_XF86Launch5 }, - { "XF86Launch6", XKB_KEY_XF86Launch6 }, - { "XF86Launch7", XKB_KEY_XF86Launch7 }, - { "XF86Launch8", XKB_KEY_XF86Launch8 }, - { "XF86Launch9", XKB_KEY_XF86Launch9 }, - { "XF86LaunchA", XKB_KEY_XF86LaunchA }, - { "XF86LaunchB", XKB_KEY_XF86LaunchB }, - { "XF86LaunchC", XKB_KEY_XF86LaunchC }, - { "XF86LaunchD", XKB_KEY_XF86LaunchD }, - { "XF86LaunchE", XKB_KEY_XF86LaunchE }, - { "XF86LaunchF", XKB_KEY_XF86LaunchF }, - { "XF86LightBulb", XKB_KEY_XF86LightBulb }, - { "XF86LogGrabInfo", XKB_KEY_XF86LogGrabInfo }, - { "XF86LogOff", XKB_KEY_XF86LogOff }, - { "XF86LogWindowTree", XKB_KEY_XF86LogWindowTree }, - { "XF86Mail", XKB_KEY_XF86Mail }, - { "XF86MailForward", XKB_KEY_XF86MailForward }, - { "XF86Market", XKB_KEY_XF86Market }, - { "XF86Meeting", XKB_KEY_XF86Meeting }, - { "XF86Memo", XKB_KEY_XF86Memo }, - { "XF86MenuKB", XKB_KEY_XF86MenuKB }, - { "XF86MenuPB", XKB_KEY_XF86MenuPB }, - { "XF86Messenger", XKB_KEY_XF86Messenger }, - { "XF86ModeLock", XKB_KEY_XF86ModeLock }, - { "XF86MonBrightnessDown", XKB_KEY_XF86MonBrightnessDown }, - { "XF86MonBrightnessUp", XKB_KEY_XF86MonBrightnessUp }, - { "XF86Music", XKB_KEY_XF86Music }, - { "XF86MyComputer", XKB_KEY_XF86MyComputer }, - { "XF86MySites", XKB_KEY_XF86MySites }, - { "XF86New", XKB_KEY_XF86New }, - { "XF86News", XKB_KEY_XF86News }, - { "XF86Next_VMode", XKB_KEY_XF86Next_VMode }, - { "XF86OfficeHome", XKB_KEY_XF86OfficeHome }, - { "XF86Open", XKB_KEY_XF86Open }, - { "XF86OpenURL", XKB_KEY_XF86OpenURL }, - { "XF86Option", XKB_KEY_XF86Option }, - { "XF86Paste", XKB_KEY_XF86Paste }, - { "XF86Phone", XKB_KEY_XF86Phone }, - { "XF86Pictures", XKB_KEY_XF86Pictures }, - { "XF86PowerDown", XKB_KEY_XF86PowerDown }, - { "XF86PowerOff", XKB_KEY_XF86PowerOff }, - { "XF86Prev_VMode", XKB_KEY_XF86Prev_VMode }, - { "XF86Q", XKB_KEY_XF86Q }, - { "XF86Red", XKB_KEY_XF86Red }, - { "XF86Refresh", XKB_KEY_XF86Refresh }, - { "XF86Reload", XKB_KEY_XF86Reload }, - { "XF86Reply", XKB_KEY_XF86Reply }, - { "XF86RockerDown", XKB_KEY_XF86RockerDown }, - { "XF86RockerEnter", XKB_KEY_XF86RockerEnter }, - { "XF86RockerUp", XKB_KEY_XF86RockerUp }, - { "XF86RotateWindows", XKB_KEY_XF86RotateWindows }, - { "XF86RotationKB", XKB_KEY_XF86RotationKB }, - { "XF86RotationPB", XKB_KEY_XF86RotationPB }, - { "XF86Save", XKB_KEY_XF86Save }, - { "XF86ScreenSaver", XKB_KEY_XF86ScreenSaver }, - { "XF86ScrollClick", XKB_KEY_XF86ScrollClick }, - { "XF86ScrollDown", XKB_KEY_XF86ScrollDown }, - { "XF86ScrollUp", XKB_KEY_XF86ScrollUp }, - { "XF86Search", XKB_KEY_XF86Search }, - { "XF86Select", XKB_KEY_XF86Select }, - { "XF86Send", XKB_KEY_XF86Send }, - { "XF86Shop", XKB_KEY_XF86Shop }, - { "XF86Sleep", XKB_KEY_XF86Sleep }, - { "XF86Spell", XKB_KEY_XF86Spell }, - { "XF86SplitScreen", XKB_KEY_XF86SplitScreen }, - { "XF86Standby", XKB_KEY_XF86Standby }, - { "XF86Start", XKB_KEY_XF86Start }, - { "XF86Stop", XKB_KEY_XF86Stop }, - { "XF86Subtitle", XKB_KEY_XF86Subtitle }, - { "XF86Support", XKB_KEY_XF86Support }, - { "XF86Suspend", XKB_KEY_XF86Suspend }, - { "XF86Switch_VT_1", XKB_KEY_XF86Switch_VT_1 }, - { "XF86Switch_VT_10", XKB_KEY_XF86Switch_VT_10 }, - { "XF86Switch_VT_11", XKB_KEY_XF86Switch_VT_11 }, - { "XF86Switch_VT_12", XKB_KEY_XF86Switch_VT_12 }, - { "XF86Switch_VT_2", XKB_KEY_XF86Switch_VT_2 }, - { "XF86Switch_VT_3", XKB_KEY_XF86Switch_VT_3 }, - { "XF86Switch_VT_4", XKB_KEY_XF86Switch_VT_4 }, - { "XF86Switch_VT_5", XKB_KEY_XF86Switch_VT_5 }, - { "XF86Switch_VT_6", XKB_KEY_XF86Switch_VT_6 }, - { "XF86Switch_VT_7", XKB_KEY_XF86Switch_VT_7 }, - { "XF86Switch_VT_8", XKB_KEY_XF86Switch_VT_8 }, - { "XF86Switch_VT_9", XKB_KEY_XF86Switch_VT_9 }, - { "XF86TaskPane", XKB_KEY_XF86TaskPane }, - { "XF86Terminal", XKB_KEY_XF86Terminal }, - { "XF86Time", XKB_KEY_XF86Time }, - { "XF86ToDoList", XKB_KEY_XF86ToDoList }, - { "XF86Tools", XKB_KEY_XF86Tools }, - { "XF86TopMenu", XKB_KEY_XF86TopMenu }, - { "XF86TouchpadOff", XKB_KEY_XF86TouchpadOff }, - { "XF86TouchpadOn", XKB_KEY_XF86TouchpadOn }, - { "XF86TouchpadToggle", XKB_KEY_XF86TouchpadToggle }, - { "XF86Travel", XKB_KEY_XF86Travel }, - { "XF86Ungrab", XKB_KEY_XF86Ungrab }, - { "XF86User1KB", XKB_KEY_XF86User1KB }, - { "XF86User2KB", XKB_KEY_XF86User2KB }, - { "XF86UserPB", XKB_KEY_XF86UserPB }, - { "XF86UWB", XKB_KEY_XF86UWB }, - { "XF86VendorHome", XKB_KEY_XF86VendorHome }, - { "XF86Video", XKB_KEY_XF86Video }, - { "XF86View", XKB_KEY_XF86View }, - { "XF86WakeUp", XKB_KEY_XF86WakeUp }, - { "XF86WebCam", XKB_KEY_XF86WebCam }, - { "XF86WheelButton", XKB_KEY_XF86WheelButton }, - { "XF86WLAN", XKB_KEY_XF86WLAN }, - { "XF86Word", XKB_KEY_XF86Word }, - { "XF86WWW", XKB_KEY_XF86WWW }, - { "XF86Xfer", XKB_KEY_XF86Xfer }, - { "XF86Yellow", XKB_KEY_XF86Yellow }, - { "XF86ZoomIn", XKB_KEY_XF86ZoomIn }, - { "XF86ZoomOut", XKB_KEY_XF86ZoomOut }, - { "Y", XKB_KEY_Y }, - { "y", XKB_KEY_y }, - { "Yacute", XKB_KEY_Yacute }, - { "yacute", XKB_KEY_yacute }, - { "Ybelowdot", XKB_KEY_Ybelowdot }, - { "ybelowdot", XKB_KEY_ybelowdot }, - { "Ycircumflex", XKB_KEY_Ycircumflex }, - { "ycircumflex", XKB_KEY_ycircumflex }, - { "ydiaeresis", XKB_KEY_ydiaeresis }, - { "Ydiaeresis", XKB_KEY_Ydiaeresis }, - { "yen", XKB_KEY_yen }, - { "Ygrave", XKB_KEY_Ygrave }, - { "ygrave", XKB_KEY_ygrave }, - { "Yhook", XKB_KEY_Yhook }, - { "yhook", XKB_KEY_yhook }, - { "Ytilde", XKB_KEY_Ytilde }, - { "ytilde", XKB_KEY_ytilde }, - { "Z", XKB_KEY_Z }, - { "z", XKB_KEY_z }, - { "Zabovedot", XKB_KEY_Zabovedot }, - { "zabovedot", XKB_KEY_zabovedot }, - { "Zacute", XKB_KEY_Zacute }, - { "zacute", XKB_KEY_zacute }, - { "Zcaron", XKB_KEY_Zcaron }, - { "zcaron", XKB_KEY_zcaron }, - { "Zen_Koho", XKB_KEY_Zen_Koho }, - { "Zenkaku", XKB_KEY_Zenkaku }, - { "Zenkaku_Hankaku", XKB_KEY_Zenkaku_Hankaku }, - { "zerosubscript", XKB_KEY_zerosubscript }, - { "zerosuperior", XKB_KEY_zerosuperior }, - { "Zstroke", XKB_KEY_Zstroke }, - { "zstroke", XKB_KEY_zstroke }, + { 0x00000030, 0 }, /* 0 */ + { 0x00000031, 2 }, /* 1 */ + { 0x00000032, 4 }, /* 2 */ + { 0x00000033, 6 }, /* 3 */ + { 0x0000fd10, 8 }, /* 3270_AltCursor */ + { 0x0000fd0e, 23 }, /* 3270_Attn */ + { 0x0000fd05, 33 }, /* 3270_BackTab */ + { 0x0000fd19, 46 }, /* 3270_ChangeScreen */ + { 0x0000fd15, 64 }, /* 3270_Copy */ + { 0x0000fd0f, 74 }, /* 3270_CursorBlink */ + { 0x0000fd1c, 91 }, /* 3270_CursorSelect */ + { 0x0000fd1a, 109 }, /* 3270_DeleteWord */ + { 0x0000fd01, 125 }, /* 3270_Duplicate */ + { 0x0000fd1e, 140 }, /* 3270_Enter */ + { 0x0000fd06, 151 }, /* 3270_EraseEOF */ + { 0x0000fd07, 165 }, /* 3270_EraseInput */ + { 0x0000fd1b, 181 }, /* 3270_ExSelect */ + { 0x0000fd02, 195 }, /* 3270_FieldMark */ + { 0x0000fd13, 210 }, /* 3270_Ident */ + { 0x0000fd12, 221 }, /* 3270_Jump */ + { 0x0000fd11, 231 }, /* 3270_KeyClick */ + { 0x0000fd04, 245 }, /* 3270_Left2 */ + { 0x0000fd0a, 256 }, /* 3270_PA1 */ + { 0x0000fd0b, 265 }, /* 3270_PA2 */ + { 0x0000fd0c, 274 }, /* 3270_PA3 */ + { 0x0000fd16, 283 }, /* 3270_Play */ + { 0x0000fd1d, 293 }, /* 3270_PrintScreen */ + { 0x0000fd09, 310 }, /* 3270_Quit */ + { 0x0000fd18, 320 }, /* 3270_Record */ + { 0x0000fd08, 332 }, /* 3270_Reset */ + { 0x0000fd03, 343 }, /* 3270_Right2 */ + { 0x0000fd14, 355 }, /* 3270_Rule */ + { 0x0000fd17, 365 }, /* 3270_Setup */ + { 0x0000fd0d, 376 }, /* 3270_Test */ + { 0x00000034, 386 }, /* 4 */ + { 0x00000035, 388 }, /* 5 */ + { 0x00000036, 390 }, /* 6 */ + { 0x00000037, 392 }, /* 7 */ + { 0x00000038, 394 }, /* 8 */ + { 0x00000039, 396 }, /* 9 */ + { 0x00000041, 398 }, /* A */ + { 0x00000061, 400 }, /* a */ + { 0x000000c1, 402 }, /* Aacute */ + { 0x000000e1, 409 }, /* aacute */ + { 0x01001ea0, 416 }, /* Abelowdot */ + { 0x01001ea1, 426 }, /* abelowdot */ + { 0x000001ff, 436 }, /* abovedot */ + { 0x000001c3, 445 }, /* Abreve */ + { 0x000001e3, 452 }, /* abreve */ + { 0x01001eae, 459 }, /* Abreveacute */ + { 0x01001eaf, 471 }, /* abreveacute */ + { 0x01001eb6, 483 }, /* Abrevebelowdot */ + { 0x01001eb7, 498 }, /* abrevebelowdot */ + { 0x01001eb0, 513 }, /* Abrevegrave */ + { 0x01001eb1, 525 }, /* abrevegrave */ + { 0x01001eb2, 537 }, /* Abrevehook */ + { 0x01001eb3, 548 }, /* abrevehook */ + { 0x01001eb4, 559 }, /* Abrevetilde */ + { 0x01001eb5, 571 }, /* abrevetilde */ + { 0x0000fe70, 583 }, /* AccessX_Enable */ + { 0x0000fe71, 598 }, /* AccessX_Feedback_Enable */ + { 0x000000c2, 622 }, /* Acircumflex */ + { 0x000000e2, 634 }, /* acircumflex */ + { 0x01001ea4, 646 }, /* Acircumflexacute */ + { 0x01001ea5, 663 }, /* acircumflexacute */ + { 0x01001eac, 680 }, /* Acircumflexbelowdot */ + { 0x01001ead, 700 }, /* acircumflexbelowdot */ + { 0x01001ea6, 720 }, /* Acircumflexgrave */ + { 0x01001ea7, 737 }, /* acircumflexgrave */ + { 0x01001ea8, 754 }, /* Acircumflexhook */ + { 0x01001ea9, 770 }, /* acircumflexhook */ + { 0x01001eaa, 786 }, /* Acircumflextilde */ + { 0x01001eab, 803 }, /* acircumflextilde */ + { 0x000000b4, 820 }, /* acute */ + { 0x000000c4, 826 }, /* Adiaeresis */ + { 0x000000e4, 837 }, /* adiaeresis */ + { 0x000000c6, 848 }, /* AE */ + { 0x000000e6, 851 }, /* ae */ + { 0x000000c0, 854 }, /* Agrave */ + { 0x000000e0, 861 }, /* agrave */ + { 0x01001ea2, 868 }, /* Ahook */ + { 0x01001ea3, 874 }, /* ahook */ + { 0x0000ffe9, 880 }, /* Alt_L */ + { 0x0000ffea, 886 }, /* Alt_R */ + { 0x000003c0, 892 }, /* Amacron */ + { 0x000003e0, 900 }, /* amacron */ + { 0x00000026, 908 }, /* ampersand */ + { 0x000001a1, 918 }, /* Aogonek */ + { 0x000001b1, 926 }, /* aogonek */ + { 0x00000027, 934 }, /* apostrophe */ + { 0x01002248, 945 }, /* approxeq */ + { 0x000008c8, 954 }, /* approximate */ + { 0x01000660, 966 }, /* Arabic_0 */ + { 0x01000661, 975 }, /* Arabic_1 */ + { 0x01000662, 984 }, /* Arabic_2 */ + { 0x01000663, 993 }, /* Arabic_3 */ + { 0x01000664, 1002 }, /* Arabic_4 */ + { 0x01000665, 1011 }, /* Arabic_5 */ + { 0x01000666, 1020 }, /* Arabic_6 */ + { 0x01000667, 1029 }, /* Arabic_7 */ + { 0x01000668, 1038 }, /* Arabic_8 */ + { 0x01000669, 1047 }, /* Arabic_9 */ + { 0x000005d9, 1056 }, /* Arabic_ain */ + { 0x000005c7, 1067 }, /* Arabic_alef */ + { 0x000005e9, 1079 }, /* Arabic_alefmaksura */ + { 0x000005c8, 1098 }, /* Arabic_beh */ + { 0x000005ac, 1109 }, /* Arabic_comma */ + { 0x000005d6, 1122 }, /* Arabic_dad */ + { 0x000005cf, 1133 }, /* Arabic_dal */ + { 0x000005ef, 1144 }, /* Arabic_damma */ + { 0x000005ec, 1157 }, /* Arabic_dammatan */ + { 0x01000688, 1173 }, /* Arabic_ddal */ + { 0x010006cc, 1185 }, /* Arabic_farsi_yeh */ + { 0x000005ee, 1202 }, /* Arabic_fatha */ + { 0x000005eb, 1215 }, /* Arabic_fathatan */ + { 0x000005e1, 1231 }, /* Arabic_feh */ + { 0x010006d4, 1242 }, /* Arabic_fullstop */ + { 0x010006af, 1258 }, /* Arabic_gaf */ + { 0x000005da, 1269 }, /* Arabic_ghain */ + { 0x000005e7, 1282 }, /* Arabic_ha */ + { 0x000005cd, 1292 }, /* Arabic_hah */ + { 0x000005c1, 1303 }, /* Arabic_hamza */ + { 0x01000654, 1316 }, /* Arabic_hamza_above */ + { 0x01000655, 1335 }, /* Arabic_hamza_below */ + { 0x000005c3, 1354 }, /* Arabic_hamzaonalef */ + { 0x000005c4, 1373 }, /* Arabic_hamzaonwaw */ + { 0x000005c6, 1391 }, /* Arabic_hamzaonyeh */ + { 0x000005c5, 1409 }, /* Arabic_hamzaunderalef */ + { 0x000005e7, 1431 }, /* Arabic_heh */ + { 0x010006be, 1442 }, /* Arabic_heh_doachashmee */ + { 0x010006c1, 1465 }, /* Arabic_heh_goal */ + { 0x000005cc, 1481 }, /* Arabic_jeem */ + { 0x01000698, 1493 }, /* Arabic_jeh */ + { 0x000005e3, 1504 }, /* Arabic_kaf */ + { 0x000005f0, 1515 }, /* Arabic_kasra */ + { 0x000005ed, 1528 }, /* Arabic_kasratan */ + { 0x010006a9, 1544 }, /* Arabic_keheh */ + { 0x000005ce, 1557 }, /* Arabic_khah */ + { 0x000005e4, 1569 }, /* Arabic_lam */ + { 0x01000653, 1580 }, /* Arabic_madda_above */ + { 0x000005c2, 1599 }, /* Arabic_maddaonalef */ + { 0x000005e5, 1618 }, /* Arabic_meem */ + { 0x000005e6, 1630 }, /* Arabic_noon */ + { 0x010006ba, 1642 }, /* Arabic_noon_ghunna */ + { 0x0100067e, 1661 }, /* Arabic_peh */ + { 0x0100066a, 1672 }, /* Arabic_percent */ + { 0x000005e2, 1687 }, /* Arabic_qaf */ + { 0x000005bf, 1698 }, /* Arabic_question_mark */ + { 0x000005d1, 1719 }, /* Arabic_ra */ + { 0x01000691, 1729 }, /* Arabic_rreh */ + { 0x000005d5, 1741 }, /* Arabic_sad */ + { 0x000005d3, 1752 }, /* Arabic_seen */ + { 0x000005bb, 1764 }, /* Arabic_semicolon */ + { 0x000005f1, 1781 }, /* Arabic_shadda */ + { 0x000005d4, 1795 }, /* Arabic_sheen */ + { 0x000005f2, 1808 }, /* Arabic_sukun */ + { 0x01000670, 1821 }, /* Arabic_superscript_alef */ + { 0x0000ff7e, 1845 }, /* Arabic_switch */ + { 0x000005d7, 1859 }, /* Arabic_tah */ + { 0x000005e0, 1870 }, /* Arabic_tatweel */ + { 0x01000686, 1885 }, /* Arabic_tcheh */ + { 0x000005ca, 1898 }, /* Arabic_teh */ + { 0x000005c9, 1909 }, /* Arabic_tehmarbuta */ + { 0x000005d0, 1927 }, /* Arabic_thal */ + { 0x000005cb, 1939 }, /* Arabic_theh */ + { 0x01000679, 1951 }, /* Arabic_tteh */ + { 0x010006a4, 1963 }, /* Arabic_veh */ + { 0x000005e8, 1974 }, /* Arabic_waw */ + { 0x000005ea, 1985 }, /* Arabic_yeh */ + { 0x010006d2, 1996 }, /* Arabic_yeh_baree */ + { 0x000005d8, 2013 }, /* Arabic_zah */ + { 0x000005d2, 2024 }, /* Arabic_zain */ + { 0x000000c5, 2036 }, /* Aring */ + { 0x000000e5, 2042 }, /* aring */ + { 0x0100055b, 2048 }, /* Armenian_accent */ + { 0x0100055c, 2064 }, /* Armenian_amanak */ + { 0x0100055a, 2080 }, /* Armenian_apostrophe */ + { 0x01000538, 2100 }, /* Armenian_AT */ + { 0x01000568, 2112 }, /* Armenian_at */ + { 0x01000531, 2124 }, /* Armenian_AYB */ + { 0x01000561, 2137 }, /* Armenian_ayb */ + { 0x01000532, 2150 }, /* Armenian_BEN */ + { 0x01000562, 2163 }, /* Armenian_ben */ + { 0x0100055d, 2176 }, /* Armenian_but */ + { 0x01000549, 2189 }, /* Armenian_CHA */ + { 0x01000579, 2202 }, /* Armenian_cha */ + { 0x01000534, 2215 }, /* Armenian_DA */ + { 0x01000564, 2227 }, /* Armenian_da */ + { 0x01000541, 2239 }, /* Armenian_DZA */ + { 0x01000571, 2252 }, /* Armenian_dza */ + { 0x01000537, 2265 }, /* Armenian_E */ + { 0x01000567, 2276 }, /* Armenian_e */ + { 0x0100055c, 2287 }, /* Armenian_exclam */ + { 0x01000556, 2303 }, /* Armenian_FE */ + { 0x01000586, 2315 }, /* Armenian_fe */ + { 0x01000589, 2327 }, /* Armenian_full_stop */ + { 0x01000542, 2346 }, /* Armenian_GHAT */ + { 0x01000572, 2360 }, /* Armenian_ghat */ + { 0x01000533, 2374 }, /* Armenian_GIM */ + { 0x01000563, 2387 }, /* Armenian_gim */ + { 0x01000545, 2400 }, /* Armenian_HI */ + { 0x01000575, 2412 }, /* Armenian_hi */ + { 0x01000540, 2424 }, /* Armenian_HO */ + { 0x01000570, 2436 }, /* Armenian_ho */ + { 0x0100058a, 2448 }, /* Armenian_hyphen */ + { 0x0100053b, 2464 }, /* Armenian_INI */ + { 0x0100056b, 2477 }, /* Armenian_ini */ + { 0x0100054b, 2490 }, /* Armenian_JE */ + { 0x0100057b, 2502 }, /* Armenian_je */ + { 0x01000554, 2514 }, /* Armenian_KE */ + { 0x01000584, 2526 }, /* Armenian_ke */ + { 0x0100053f, 2538 }, /* Armenian_KEN */ + { 0x0100056f, 2551 }, /* Armenian_ken */ + { 0x0100053d, 2564 }, /* Armenian_KHE */ + { 0x0100056d, 2577 }, /* Armenian_khe */ + { 0x01000587, 2590 }, /* Armenian_ligature_ew */ + { 0x0100053c, 2611 }, /* Armenian_LYUN */ + { 0x0100056c, 2625 }, /* Armenian_lyun */ + { 0x01000544, 2639 }, /* Armenian_MEN */ + { 0x01000574, 2652 }, /* Armenian_men */ + { 0x01000546, 2665 }, /* Armenian_NU */ + { 0x01000576, 2677 }, /* Armenian_nu */ + { 0x01000555, 2689 }, /* Armenian_O */ + { 0x01000585, 2700 }, /* Armenian_o */ + { 0x0100055e, 2711 }, /* Armenian_paruyk */ + { 0x0100054a, 2727 }, /* Armenian_PE */ + { 0x0100057a, 2739 }, /* Armenian_pe */ + { 0x01000553, 2751 }, /* Armenian_PYUR */ + { 0x01000583, 2765 }, /* Armenian_pyur */ + { 0x0100055e, 2779 }, /* Armenian_question */ + { 0x0100054c, 2797 }, /* Armenian_RA */ + { 0x0100057c, 2809 }, /* Armenian_ra */ + { 0x01000550, 2821 }, /* Armenian_RE */ + { 0x01000580, 2833 }, /* Armenian_re */ + { 0x0100054d, 2845 }, /* Armenian_SE */ + { 0x0100057d, 2857 }, /* Armenian_se */ + { 0x0100055d, 2869 }, /* Armenian_separation_mark */ + { 0x01000547, 2894 }, /* Armenian_SHA */ + { 0x01000577, 2907 }, /* Armenian_sha */ + { 0x0100055b, 2920 }, /* Armenian_shesht */ + { 0x01000543, 2936 }, /* Armenian_TCHE */ + { 0x01000573, 2950 }, /* Armenian_tche */ + { 0x01000539, 2964 }, /* Armenian_TO */ + { 0x01000569, 2976 }, /* Armenian_to */ + { 0x0100053e, 2988 }, /* Armenian_TSA */ + { 0x0100056e, 3001 }, /* Armenian_tsa */ + { 0x01000551, 3014 }, /* Armenian_TSO */ + { 0x01000581, 3027 }, /* Armenian_tso */ + { 0x0100054f, 3040 }, /* Armenian_TYUN */ + { 0x0100057f, 3054 }, /* Armenian_tyun */ + { 0x01000589, 3068 }, /* Armenian_verjaket */ + { 0x0100054e, 3086 }, /* Armenian_VEV */ + { 0x0100057e, 3099 }, /* Armenian_vev */ + { 0x01000548, 3112 }, /* Armenian_VO */ + { 0x01000578, 3124 }, /* Armenian_vo */ + { 0x01000552, 3136 }, /* Armenian_VYUN */ + { 0x01000582, 3150 }, /* Armenian_vyun */ + { 0x01000535, 3164 }, /* Armenian_YECH */ + { 0x01000565, 3178 }, /* Armenian_yech */ + { 0x0100058a, 3192 }, /* Armenian_yentamna */ + { 0x01000536, 3210 }, /* Armenian_ZA */ + { 0x01000566, 3222 }, /* Armenian_za */ + { 0x0100053a, 3234 }, /* Armenian_ZHE */ + { 0x0100056a, 3247 }, /* Armenian_zhe */ + { 0x0000005e, 3260 }, /* asciicircum */ + { 0x0000007e, 3272 }, /* asciitilde */ + { 0x0000002a, 3283 }, /* asterisk */ + { 0x00000040, 3292 }, /* at */ + { 0x000000c3, 3295 }, /* Atilde */ + { 0x000000e3, 3302 }, /* atilde */ + { 0x0000fe7a, 3309 }, /* AudibleBell_Enable */ + { 0x00000042, 3328 }, /* B */ + { 0x00000062, 3330 }, /* b */ + { 0x01001e02, 3332 }, /* Babovedot */ + { 0x01001e03, 3342 }, /* babovedot */ + { 0x0000005c, 3352 }, /* backslash */ + { 0x0000ff08, 3362 }, /* BackSpace */ + { 0x1000ff74, 3372 }, /* BackTab */ + { 0x00000af4, 3380 }, /* ballotcross */ + { 0x0000007c, 3392 }, /* bar */ + { 0x01002235, 3396 }, /* because */ + { 0x0000ff58, 3404 }, /* Begin */ + { 0x000009df, 3410 }, /* blank */ + { 0x100000fc, 3416 }, /* block */ + { 0x000008a5, 3422 }, /* botintegral */ + { 0x000008ac, 3434 }, /* botleftparens */ + { 0x000008a8, 3448 }, /* botleftsqbracket */ + { 0x000008b2, 3465 }, /* botleftsummation */ + { 0x000008ae, 3482 }, /* botrightparens */ + { 0x000008aa, 3497 }, /* botrightsqbracket */ + { 0x000008b6, 3515 }, /* botrightsummation */ + { 0x000009f6, 3533 }, /* bott */ + { 0x000008b4, 3538 }, /* botvertsummationconnector */ + { 0x0000fe74, 3564 }, /* BounceKeys_Enable */ + { 0x0000007b, 3582 }, /* braceleft */ + { 0x0000007d, 3592 }, /* braceright */ + { 0x0000005b, 3603 }, /* bracketleft */ + { 0x0000005d, 3615 }, /* bracketright */ + { 0x01002800, 3628 }, /* braille_blank */ + { 0x0000fff1, 3642 }, /* braille_dot_1 */ + { 0x0000fffa, 3656 }, /* braille_dot_10 */ + { 0x0000fff2, 3671 }, /* braille_dot_2 */ + { 0x0000fff3, 3685 }, /* braille_dot_3 */ + { 0x0000fff4, 3699 }, /* braille_dot_4 */ + { 0x0000fff5, 3713 }, /* braille_dot_5 */ + { 0x0000fff6, 3727 }, /* braille_dot_6 */ + { 0x0000fff7, 3741 }, /* braille_dot_7 */ + { 0x0000fff8, 3755 }, /* braille_dot_8 */ + { 0x0000fff9, 3769 }, /* braille_dot_9 */ + { 0x01002801, 3783 }, /* braille_dots_1 */ + { 0x01002803, 3798 }, /* braille_dots_12 */ + { 0x01002807, 3814 }, /* braille_dots_123 */ + { 0x0100280f, 3831 }, /* braille_dots_1234 */ + { 0x0100281f, 3849 }, /* braille_dots_12345 */ + { 0x0100283f, 3868 }, /* braille_dots_123456 */ + { 0x0100287f, 3888 }, /* braille_dots_1234567 */ + { 0x010028ff, 3909 }, /* braille_dots_12345678 */ + { 0x010028bf, 3931 }, /* braille_dots_1234568 */ + { 0x0100285f, 3952 }, /* braille_dots_123457 */ + { 0x010028df, 3972 }, /* braille_dots_1234578 */ + { 0x0100289f, 3993 }, /* braille_dots_123458 */ + { 0x0100282f, 4013 }, /* braille_dots_12346 */ + { 0x0100286f, 4032 }, /* braille_dots_123467 */ + { 0x010028ef, 4052 }, /* braille_dots_1234678 */ + { 0x010028af, 4073 }, /* braille_dots_123468 */ + { 0x0100284f, 4093 }, /* braille_dots_12347 */ + { 0x010028cf, 4112 }, /* braille_dots_123478 */ + { 0x0100288f, 4132 }, /* braille_dots_12348 */ + { 0x01002817, 4151 }, /* braille_dots_1235 */ + { 0x01002837, 4169 }, /* braille_dots_12356 */ + { 0x01002877, 4188 }, /* braille_dots_123567 */ + { 0x010028f7, 4208 }, /* braille_dots_1235678 */ + { 0x010028b7, 4229 }, /* braille_dots_123568 */ + { 0x01002857, 4249 }, /* braille_dots_12357 */ + { 0x010028d7, 4268 }, /* braille_dots_123578 */ + { 0x01002897, 4288 }, /* braille_dots_12358 */ + { 0x01002827, 4307 }, /* braille_dots_1236 */ + { 0x01002867, 4325 }, /* braille_dots_12367 */ + { 0x010028e7, 4344 }, /* braille_dots_123678 */ + { 0x010028a7, 4364 }, /* braille_dots_12368 */ + { 0x01002847, 4383 }, /* braille_dots_1237 */ + { 0x010028c7, 4401 }, /* braille_dots_12378 */ + { 0x01002887, 4420 }, /* braille_dots_1238 */ + { 0x0100280b, 4438 }, /* braille_dots_124 */ + { 0x0100281b, 4455 }, /* braille_dots_1245 */ + { 0x0100283b, 4473 }, /* braille_dots_12456 */ + { 0x0100287b, 4492 }, /* braille_dots_124567 */ + { 0x010028fb, 4512 }, /* braille_dots_1245678 */ + { 0x010028bb, 4533 }, /* braille_dots_124568 */ + { 0x0100285b, 4553 }, /* braille_dots_12457 */ + { 0x010028db, 4572 }, /* braille_dots_124578 */ + { 0x0100289b, 4592 }, /* braille_dots_12458 */ + { 0x0100282b, 4611 }, /* braille_dots_1246 */ + { 0x0100286b, 4629 }, /* braille_dots_12467 */ + { 0x010028eb, 4648 }, /* braille_dots_124678 */ + { 0x010028ab, 4668 }, /* braille_dots_12468 */ + { 0x0100284b, 4687 }, /* braille_dots_1247 */ + { 0x010028cb, 4705 }, /* braille_dots_12478 */ + { 0x0100288b, 4724 }, /* braille_dots_1248 */ + { 0x01002813, 4742 }, /* braille_dots_125 */ + { 0x01002833, 4759 }, /* braille_dots_1256 */ + { 0x01002873, 4777 }, /* braille_dots_12567 */ + { 0x010028f3, 4796 }, /* braille_dots_125678 */ + { 0x010028b3, 4816 }, /* braille_dots_12568 */ + { 0x01002853, 4835 }, /* braille_dots_1257 */ + { 0x010028d3, 4853 }, /* braille_dots_12578 */ + { 0x01002893, 4872 }, /* braille_dots_1258 */ + { 0x01002823, 4890 }, /* braille_dots_126 */ + { 0x01002863, 4907 }, /* braille_dots_1267 */ + { 0x010028e3, 4925 }, /* braille_dots_12678 */ + { 0x010028a3, 4944 }, /* braille_dots_1268 */ + { 0x01002843, 4962 }, /* braille_dots_127 */ + { 0x010028c3, 4979 }, /* braille_dots_1278 */ + { 0x01002883, 4997 }, /* braille_dots_128 */ + { 0x01002805, 5014 }, /* braille_dots_13 */ + { 0x0100280d, 5030 }, /* braille_dots_134 */ + { 0x0100281d, 5047 }, /* braille_dots_1345 */ + { 0x0100283d, 5065 }, /* braille_dots_13456 */ + { 0x0100287d, 5084 }, /* braille_dots_134567 */ + { 0x010028fd, 5104 }, /* braille_dots_1345678 */ + { 0x010028bd, 5125 }, /* braille_dots_134568 */ + { 0x0100285d, 5145 }, /* braille_dots_13457 */ + { 0x010028dd, 5164 }, /* braille_dots_134578 */ + { 0x0100289d, 5184 }, /* braille_dots_13458 */ + { 0x0100282d, 5203 }, /* braille_dots_1346 */ + { 0x0100286d, 5221 }, /* braille_dots_13467 */ + { 0x010028ed, 5240 }, /* braille_dots_134678 */ + { 0x010028ad, 5260 }, /* braille_dots_13468 */ + { 0x0100284d, 5279 }, /* braille_dots_1347 */ + { 0x010028cd, 5297 }, /* braille_dots_13478 */ + { 0x0100288d, 5316 }, /* braille_dots_1348 */ + { 0x01002815, 5334 }, /* braille_dots_135 */ + { 0x01002835, 5351 }, /* braille_dots_1356 */ + { 0x01002875, 5369 }, /* braille_dots_13567 */ + { 0x010028f5, 5388 }, /* braille_dots_135678 */ + { 0x010028b5, 5408 }, /* braille_dots_13568 */ + { 0x01002855, 5427 }, /* braille_dots_1357 */ + { 0x010028d5, 5445 }, /* braille_dots_13578 */ + { 0x01002895, 5464 }, /* braille_dots_1358 */ + { 0x01002825, 5482 }, /* braille_dots_136 */ + { 0x01002865, 5499 }, /* braille_dots_1367 */ + { 0x010028e5, 5517 }, /* braille_dots_13678 */ + { 0x010028a5, 5536 }, /* braille_dots_1368 */ + { 0x01002845, 5554 }, /* braille_dots_137 */ + { 0x010028c5, 5571 }, /* braille_dots_1378 */ + { 0x01002885, 5589 }, /* braille_dots_138 */ + { 0x01002809, 5606 }, /* braille_dots_14 */ + { 0x01002819, 5622 }, /* braille_dots_145 */ + { 0x01002839, 5639 }, /* braille_dots_1456 */ + { 0x01002879, 5657 }, /* braille_dots_14567 */ + { 0x010028f9, 5676 }, /* braille_dots_145678 */ + { 0x010028b9, 5696 }, /* braille_dots_14568 */ + { 0x01002859, 5715 }, /* braille_dots_1457 */ + { 0x010028d9, 5733 }, /* braille_dots_14578 */ + { 0x01002899, 5752 }, /* braille_dots_1458 */ + { 0x01002829, 5770 }, /* braille_dots_146 */ + { 0x01002869, 5787 }, /* braille_dots_1467 */ + { 0x010028e9, 5805 }, /* braille_dots_14678 */ + { 0x010028a9, 5824 }, /* braille_dots_1468 */ + { 0x01002849, 5842 }, /* braille_dots_147 */ + { 0x010028c9, 5859 }, /* braille_dots_1478 */ + { 0x01002889, 5877 }, /* braille_dots_148 */ + { 0x01002811, 5894 }, /* braille_dots_15 */ + { 0x01002831, 5910 }, /* braille_dots_156 */ + { 0x01002871, 5927 }, /* braille_dots_1567 */ + { 0x010028f1, 5945 }, /* braille_dots_15678 */ + { 0x010028b1, 5964 }, /* braille_dots_1568 */ + { 0x01002851, 5982 }, /* braille_dots_157 */ + { 0x010028d1, 5999 }, /* braille_dots_1578 */ + { 0x01002891, 6017 }, /* braille_dots_158 */ + { 0x01002821, 6034 }, /* braille_dots_16 */ + { 0x01002861, 6050 }, /* braille_dots_167 */ + { 0x010028e1, 6067 }, /* braille_dots_1678 */ + { 0x010028a1, 6085 }, /* braille_dots_168 */ + { 0x01002841, 6102 }, /* braille_dots_17 */ + { 0x010028c1, 6118 }, /* braille_dots_178 */ + { 0x01002881, 6135 }, /* braille_dots_18 */ + { 0x01002802, 6151 }, /* braille_dots_2 */ + { 0x01002806, 6166 }, /* braille_dots_23 */ + { 0x0100280e, 6182 }, /* braille_dots_234 */ + { 0x0100281e, 6199 }, /* braille_dots_2345 */ + { 0x0100283e, 6217 }, /* braille_dots_23456 */ + { 0x0100287e, 6236 }, /* braille_dots_234567 */ + { 0x010028fe, 6256 }, /* braille_dots_2345678 */ + { 0x010028be, 6277 }, /* braille_dots_234568 */ + { 0x0100285e, 6297 }, /* braille_dots_23457 */ + { 0x010028de, 6316 }, /* braille_dots_234578 */ + { 0x0100289e, 6336 }, /* braille_dots_23458 */ + { 0x0100282e, 6355 }, /* braille_dots_2346 */ + { 0x0100286e, 6373 }, /* braille_dots_23467 */ + { 0x010028ee, 6392 }, /* braille_dots_234678 */ + { 0x010028ae, 6412 }, /* braille_dots_23468 */ + { 0x0100284e, 6431 }, /* braille_dots_2347 */ + { 0x010028ce, 6449 }, /* braille_dots_23478 */ + { 0x0100288e, 6468 }, /* braille_dots_2348 */ + { 0x01002816, 6486 }, /* braille_dots_235 */ + { 0x01002836, 6503 }, /* braille_dots_2356 */ + { 0x01002876, 6521 }, /* braille_dots_23567 */ + { 0x010028f6, 6540 }, /* braille_dots_235678 */ + { 0x010028b6, 6560 }, /* braille_dots_23568 */ + { 0x01002856, 6579 }, /* braille_dots_2357 */ + { 0x010028d6, 6597 }, /* braille_dots_23578 */ + { 0x01002896, 6616 }, /* braille_dots_2358 */ + { 0x01002826, 6634 }, /* braille_dots_236 */ + { 0x01002866, 6651 }, /* braille_dots_2367 */ + { 0x010028e6, 6669 }, /* braille_dots_23678 */ + { 0x010028a6, 6688 }, /* braille_dots_2368 */ + { 0x01002846, 6706 }, /* braille_dots_237 */ + { 0x010028c6, 6723 }, /* braille_dots_2378 */ + { 0x01002886, 6741 }, /* braille_dots_238 */ + { 0x0100280a, 6758 }, /* braille_dots_24 */ + { 0x0100281a, 6774 }, /* braille_dots_245 */ + { 0x0100283a, 6791 }, /* braille_dots_2456 */ + { 0x0100287a, 6809 }, /* braille_dots_24567 */ + { 0x010028fa, 6828 }, /* braille_dots_245678 */ + { 0x010028ba, 6848 }, /* braille_dots_24568 */ + { 0x0100285a, 6867 }, /* braille_dots_2457 */ + { 0x010028da, 6885 }, /* braille_dots_24578 */ + { 0x0100289a, 6904 }, /* braille_dots_2458 */ + { 0x0100282a, 6922 }, /* braille_dots_246 */ + { 0x0100286a, 6939 }, /* braille_dots_2467 */ + { 0x010028ea, 6957 }, /* braille_dots_24678 */ + { 0x010028aa, 6976 }, /* braille_dots_2468 */ + { 0x0100284a, 6994 }, /* braille_dots_247 */ + { 0x010028ca, 7011 }, /* braille_dots_2478 */ + { 0x0100288a, 7029 }, /* braille_dots_248 */ + { 0x01002812, 7046 }, /* braille_dots_25 */ + { 0x01002832, 7062 }, /* braille_dots_256 */ + { 0x01002872, 7079 }, /* braille_dots_2567 */ + { 0x010028f2, 7097 }, /* braille_dots_25678 */ + { 0x010028b2, 7116 }, /* braille_dots_2568 */ + { 0x01002852, 7134 }, /* braille_dots_257 */ + { 0x010028d2, 7151 }, /* braille_dots_2578 */ + { 0x01002892, 7169 }, /* braille_dots_258 */ + { 0x01002822, 7186 }, /* braille_dots_26 */ + { 0x01002862, 7202 }, /* braille_dots_267 */ + { 0x010028e2, 7219 }, /* braille_dots_2678 */ + { 0x010028a2, 7237 }, /* braille_dots_268 */ + { 0x01002842, 7254 }, /* braille_dots_27 */ + { 0x010028c2, 7270 }, /* braille_dots_278 */ + { 0x01002882, 7287 }, /* braille_dots_28 */ + { 0x01002804, 7303 }, /* braille_dots_3 */ + { 0x0100280c, 7318 }, /* braille_dots_34 */ + { 0x0100281c, 7334 }, /* braille_dots_345 */ + { 0x0100283c, 7351 }, /* braille_dots_3456 */ + { 0x0100287c, 7369 }, /* braille_dots_34567 */ + { 0x010028fc, 7388 }, /* braille_dots_345678 */ + { 0x010028bc, 7408 }, /* braille_dots_34568 */ + { 0x0100285c, 7427 }, /* braille_dots_3457 */ + { 0x010028dc, 7445 }, /* braille_dots_34578 */ + { 0x0100289c, 7464 }, /* braille_dots_3458 */ + { 0x0100282c, 7482 }, /* braille_dots_346 */ + { 0x0100286c, 7499 }, /* braille_dots_3467 */ + { 0x010028ec, 7517 }, /* braille_dots_34678 */ + { 0x010028ac, 7536 }, /* braille_dots_3468 */ + { 0x0100284c, 7554 }, /* braille_dots_347 */ + { 0x010028cc, 7571 }, /* braille_dots_3478 */ + { 0x0100288c, 7589 }, /* braille_dots_348 */ + { 0x01002814, 7606 }, /* braille_dots_35 */ + { 0x01002834, 7622 }, /* braille_dots_356 */ + { 0x01002874, 7639 }, /* braille_dots_3567 */ + { 0x010028f4, 7657 }, /* braille_dots_35678 */ + { 0x010028b4, 7676 }, /* braille_dots_3568 */ + { 0x01002854, 7694 }, /* braille_dots_357 */ + { 0x010028d4, 7711 }, /* braille_dots_3578 */ + { 0x01002894, 7729 }, /* braille_dots_358 */ + { 0x01002824, 7746 }, /* braille_dots_36 */ + { 0x01002864, 7762 }, /* braille_dots_367 */ + { 0x010028e4, 7779 }, /* braille_dots_3678 */ + { 0x010028a4, 7797 }, /* braille_dots_368 */ + { 0x01002844, 7814 }, /* braille_dots_37 */ + { 0x010028c4, 7830 }, /* braille_dots_378 */ + { 0x01002884, 7847 }, /* braille_dots_38 */ + { 0x01002808, 7863 }, /* braille_dots_4 */ + { 0x01002818, 7878 }, /* braille_dots_45 */ + { 0x01002838, 7894 }, /* braille_dots_456 */ + { 0x01002878, 7911 }, /* braille_dots_4567 */ + { 0x010028f8, 7929 }, /* braille_dots_45678 */ + { 0x010028b8, 7948 }, /* braille_dots_4568 */ + { 0x01002858, 7966 }, /* braille_dots_457 */ + { 0x010028d8, 7983 }, /* braille_dots_4578 */ + { 0x01002898, 8001 }, /* braille_dots_458 */ + { 0x01002828, 8018 }, /* braille_dots_46 */ + { 0x01002868, 8034 }, /* braille_dots_467 */ + { 0x010028e8, 8051 }, /* braille_dots_4678 */ + { 0x010028a8, 8069 }, /* braille_dots_468 */ + { 0x01002848, 8086 }, /* braille_dots_47 */ + { 0x010028c8, 8102 }, /* braille_dots_478 */ + { 0x01002888, 8119 }, /* braille_dots_48 */ + { 0x01002810, 8135 }, /* braille_dots_5 */ + { 0x01002830, 8150 }, /* braille_dots_56 */ + { 0x01002870, 8166 }, /* braille_dots_567 */ + { 0x010028f0, 8183 }, /* braille_dots_5678 */ + { 0x010028b0, 8201 }, /* braille_dots_568 */ + { 0x01002850, 8218 }, /* braille_dots_57 */ + { 0x010028d0, 8234 }, /* braille_dots_578 */ + { 0x01002890, 8251 }, /* braille_dots_58 */ + { 0x01002820, 8267 }, /* braille_dots_6 */ + { 0x01002860, 8282 }, /* braille_dots_67 */ + { 0x010028e0, 8298 }, /* braille_dots_678 */ + { 0x010028a0, 8315 }, /* braille_dots_68 */ + { 0x01002840, 8331 }, /* braille_dots_7 */ + { 0x010028c0, 8346 }, /* braille_dots_78 */ + { 0x01002880, 8362 }, /* braille_dots_8 */ + { 0x0000ff6b, 8377 }, /* Break */ + { 0x000001a2, 8383 }, /* breve */ + { 0x000000a6, 8389 }, /* brokenbar */ + { 0x000006ae, 8399 }, /* Byelorussian_shortu */ + { 0x000006be, 8419 }, /* Byelorussian_SHORTU */ + { 0x00000043, 8439 }, /* C */ + { 0x00000063, 8441 }, /* c */ + { 0x0000fea3, 8443 }, /* c_h */ + { 0x0000fea4, 8447 }, /* C_h */ + { 0x0000fea5, 8451 }, /* C_H */ + { 0x000002c5, 8455 }, /* Cabovedot */ + { 0x000002e5, 8465 }, /* cabovedot */ + { 0x000001c6, 8475 }, /* Cacute */ + { 0x000001e6, 8482 }, /* cacute */ + { 0x0000ff69, 8489 }, /* Cancel */ + { 0x0000ffe5, 8496 }, /* Caps_Lock */ + { 0x00000ab8, 8506 }, /* careof */ + { 0x00000afc, 8513 }, /* caret */ + { 0x000001b7, 8519 }, /* caron */ + { 0x000001c8, 8525 }, /* Ccaron */ + { 0x000001e8, 8532 }, /* ccaron */ + { 0x000000c7, 8539 }, /* Ccedilla */ + { 0x000000e7, 8548 }, /* ccedilla */ + { 0x000002c6, 8557 }, /* Ccircumflex */ + { 0x000002e6, 8569 }, /* ccircumflex */ + { 0x000000b8, 8581 }, /* cedilla */ + { 0x000000a2, 8589 }, /* cent */ + { 0x0000fea0, 8594 }, /* ch */ + { 0x0000fea1, 8597 }, /* Ch */ + { 0x0000fea2, 8600 }, /* CH */ + { 0x000009e1, 8603 }, /* checkerboard */ + { 0x00000af3, 8616 }, /* checkmark */ + { 0x00000bcf, 8626 }, /* circle */ + { 0x0000ff0b, 8633 }, /* Clear */ + { 0x1000ff6f, 8639 }, /* ClearLine */ + { 0x00000aec, 8649 }, /* club */ + { 0x0000ff37, 8654 }, /* Codeinput */ + { 0x0000003a, 8664 }, /* colon */ + { 0x010020a1, 8670 }, /* ColonSign */ + { 0x0000002c, 8680 }, /* comma */ + { 0x0100220b, 8686 }, /* containsas */ + { 0x0000ffe3, 8697 }, /* Control_L */ + { 0x0000ffe4, 8707 }, /* Control_R */ + { 0x000000a9, 8717 }, /* copyright */ + { 0x000009e4, 8727 }, /* cr */ + { 0x000009ee, 8730 }, /* crossinglines */ + { 0x010020a2, 8744 }, /* CruzeiroSign */ + { 0x0100221b, 8757 }, /* cuberoot */ + { 0x000000a4, 8766 }, /* currency */ + { 0x00000aff, 8775 }, /* cursor */ + { 0x000006c1, 8782 }, /* Cyrillic_a */ + { 0x000006e1, 8793 }, /* Cyrillic_A */ + { 0x000006c2, 8804 }, /* Cyrillic_be */ + { 0x000006e2, 8816 }, /* Cyrillic_BE */ + { 0x000006de, 8828 }, /* Cyrillic_che */ + { 0x000006fe, 8841 }, /* Cyrillic_CHE */ + { 0x010004b6, 8854 }, /* Cyrillic_CHE_descender */ + { 0x010004b7, 8877 }, /* Cyrillic_che_descender */ + { 0x010004b8, 8900 }, /* Cyrillic_CHE_vertstroke */ + { 0x010004b9, 8924 }, /* Cyrillic_che_vertstroke */ + { 0x000006c4, 8948 }, /* Cyrillic_de */ + { 0x000006e4, 8960 }, /* Cyrillic_DE */ + { 0x000006af, 8972 }, /* Cyrillic_dzhe */ + { 0x000006bf, 8986 }, /* Cyrillic_DZHE */ + { 0x000006dc, 9000 }, /* Cyrillic_e */ + { 0x000006fc, 9011 }, /* Cyrillic_E */ + { 0x000006c6, 9022 }, /* Cyrillic_ef */ + { 0x000006e6, 9034 }, /* Cyrillic_EF */ + { 0x000006cc, 9046 }, /* Cyrillic_el */ + { 0x000006ec, 9058 }, /* Cyrillic_EL */ + { 0x000006cd, 9070 }, /* Cyrillic_em */ + { 0x000006ed, 9082 }, /* Cyrillic_EM */ + { 0x000006ce, 9094 }, /* Cyrillic_en */ + { 0x000006ee, 9106 }, /* Cyrillic_EN */ + { 0x010004a2, 9118 }, /* Cyrillic_EN_descender */ + { 0x010004a3, 9140 }, /* Cyrillic_en_descender */ + { 0x000006d2, 9162 }, /* Cyrillic_er */ + { 0x000006f2, 9174 }, /* Cyrillic_ER */ + { 0x000006d3, 9186 }, /* Cyrillic_es */ + { 0x000006f3, 9198 }, /* Cyrillic_ES */ + { 0x000006c7, 9210 }, /* Cyrillic_ghe */ + { 0x000006e7, 9223 }, /* Cyrillic_GHE */ + { 0x01000492, 9236 }, /* Cyrillic_GHE_bar */ + { 0x01000493, 9253 }, /* Cyrillic_ghe_bar */ + { 0x000006c8, 9270 }, /* Cyrillic_ha */ + { 0x000006e8, 9282 }, /* Cyrillic_HA */ + { 0x010004b2, 9294 }, /* Cyrillic_HA_descender */ + { 0x010004b3, 9316 }, /* Cyrillic_ha_descender */ + { 0x000006df, 9338 }, /* Cyrillic_hardsign */ + { 0x000006ff, 9356 }, /* Cyrillic_HARDSIGN */ + { 0x000006c9, 9374 }, /* Cyrillic_i */ + { 0x000006e9, 9385 }, /* Cyrillic_I */ + { 0x010004e2, 9396 }, /* Cyrillic_I_macron */ + { 0x010004e3, 9414 }, /* Cyrillic_i_macron */ + { 0x000006c5, 9432 }, /* Cyrillic_ie */ + { 0x000006e5, 9444 }, /* Cyrillic_IE */ + { 0x000006a3, 9456 }, /* Cyrillic_io */ + { 0x000006b3, 9468 }, /* Cyrillic_IO */ + { 0x000006a8, 9480 }, /* Cyrillic_je */ + { 0x000006b8, 9492 }, /* Cyrillic_JE */ + { 0x000006cb, 9504 }, /* Cyrillic_ka */ + { 0x000006eb, 9516 }, /* Cyrillic_KA */ + { 0x0100049a, 9528 }, /* Cyrillic_KA_descender */ + { 0x0100049b, 9550 }, /* Cyrillic_ka_descender */ + { 0x0100049c, 9572 }, /* Cyrillic_KA_vertstroke */ + { 0x0100049d, 9595 }, /* Cyrillic_ka_vertstroke */ + { 0x000006a9, 9618 }, /* Cyrillic_lje */ + { 0x000006b9, 9631 }, /* Cyrillic_LJE */ + { 0x000006aa, 9644 }, /* Cyrillic_nje */ + { 0x000006ba, 9657 }, /* Cyrillic_NJE */ + { 0x000006cf, 9670 }, /* Cyrillic_o */ + { 0x000006ef, 9681 }, /* Cyrillic_O */ + { 0x010004e8, 9692 }, /* Cyrillic_O_bar */ + { 0x010004e9, 9707 }, /* Cyrillic_o_bar */ + { 0x000006d0, 9722 }, /* Cyrillic_pe */ + { 0x000006f0, 9734 }, /* Cyrillic_PE */ + { 0x010004d8, 9746 }, /* Cyrillic_SCHWA */ + { 0x010004d9, 9761 }, /* Cyrillic_schwa */ + { 0x000006db, 9776 }, /* Cyrillic_sha */ + { 0x000006fb, 9789 }, /* Cyrillic_SHA */ + { 0x000006dd, 9802 }, /* Cyrillic_shcha */ + { 0x000006fd, 9817 }, /* Cyrillic_SHCHA */ + { 0x010004ba, 9832 }, /* Cyrillic_SHHA */ + { 0x010004bb, 9846 }, /* Cyrillic_shha */ + { 0x000006ca, 9860 }, /* Cyrillic_shorti */ + { 0x000006ea, 9876 }, /* Cyrillic_SHORTI */ + { 0x000006d8, 9892 }, /* Cyrillic_softsign */ + { 0x000006f8, 9910 }, /* Cyrillic_SOFTSIGN */ + { 0x000006d4, 9928 }, /* Cyrillic_te */ + { 0x000006f4, 9940 }, /* Cyrillic_TE */ + { 0x000006c3, 9952 }, /* Cyrillic_tse */ + { 0x000006e3, 9965 }, /* Cyrillic_TSE */ + { 0x000006d5, 9978 }, /* Cyrillic_u */ + { 0x000006f5, 9989 }, /* Cyrillic_U */ + { 0x010004ee, 10000 }, /* Cyrillic_U_macron */ + { 0x010004ef, 10018 }, /* Cyrillic_u_macron */ + { 0x010004ae, 10036 }, /* Cyrillic_U_straight */ + { 0x010004af, 10056 }, /* Cyrillic_u_straight */ + { 0x010004b0, 10076 }, /* Cyrillic_U_straight_bar */ + { 0x010004b1, 10100 }, /* Cyrillic_u_straight_bar */ + { 0x000006d7, 10124 }, /* Cyrillic_ve */ + { 0x000006f7, 10136 }, /* Cyrillic_VE */ + { 0x000006d1, 10148 }, /* Cyrillic_ya */ + { 0x000006f1, 10160 }, /* Cyrillic_YA */ + { 0x000006d9, 10172 }, /* Cyrillic_yeru */ + { 0x000006f9, 10186 }, /* Cyrillic_YERU */ + { 0x000006c0, 10200 }, /* Cyrillic_yu */ + { 0x000006e0, 10212 }, /* Cyrillic_YU */ + { 0x000006da, 10224 }, /* Cyrillic_ze */ + { 0x000006fa, 10236 }, /* Cyrillic_ZE */ + { 0x000006d6, 10248 }, /* Cyrillic_zhe */ + { 0x000006f6, 10261 }, /* Cyrillic_ZHE */ + { 0x01000496, 10274 }, /* Cyrillic_ZHE_descender */ + { 0x01000497, 10297 }, /* Cyrillic_zhe_descender */ + { 0x00000044, 10320 }, /* D */ + { 0x00000064, 10322 }, /* d */ + { 0x01001e0a, 10324 }, /* Dabovedot */ + { 0x01001e0b, 10334 }, /* dabovedot */ + { 0x1000fe27, 10344 }, /* Dacute_accent */ + { 0x00000af1, 10358 }, /* dagger */ + { 0x000001cf, 10365 }, /* Dcaron */ + { 0x000001ef, 10372 }, /* dcaron */ + { 0x1000fe2c, 10379 }, /* Dcedilla_accent */ + { 0x1000fe5e, 10395 }, /* Dcircumflex_accent */ + { 0x1000fe22, 10414 }, /* Ddiaeresis */ + { 0x0000fe80, 10425 }, /* dead_a */ + { 0x0000fe81, 10432 }, /* dead_A */ + { 0x0000fe64, 10439 }, /* dead_abovecomma */ + { 0x0000fe56, 10455 }, /* dead_abovedot */ + { 0x0000fe65, 10469 }, /* dead_abovereversedcomma */ + { 0x0000fe58, 10493 }, /* dead_abovering */ + { 0x0000fe91, 10508 }, /* dead_aboveverticalline */ + { 0x0000fe51, 10531 }, /* dead_acute */ + { 0x0000fe6b, 10542 }, /* dead_belowbreve */ + { 0x0000fe69, 10558 }, /* dead_belowcircumflex */ + { 0x0000fe6e, 10579 }, /* dead_belowcomma */ + { 0x0000fe6c, 10595 }, /* dead_belowdiaeresis */ + { 0x0000fe60, 10615 }, /* dead_belowdot */ + { 0x0000fe68, 10629 }, /* dead_belowmacron */ + { 0x0000fe67, 10646 }, /* dead_belowring */ + { 0x0000fe6a, 10661 }, /* dead_belowtilde */ + { 0x0000fe92, 10677 }, /* dead_belowverticalline */ + { 0x0000fe55, 10700 }, /* dead_breve */ + { 0x0000fe8b, 10711 }, /* dead_capital_schwa */ + { 0x0000fe5a, 10730 }, /* dead_caron */ + { 0x0000fe5b, 10741 }, /* dead_cedilla */ + { 0x0000fe52, 10754 }, /* dead_circumflex */ + { 0x0000fe6f, 10770 }, /* dead_currency */ + { 0x0000fe65, 10784 }, /* dead_dasia */ + { 0x0000fe57, 10795 }, /* dead_diaeresis */ + { 0x0000fe59, 10810 }, /* dead_doubleacute */ + { 0x0000fe66, 10827 }, /* dead_doublegrave */ + { 0x0000fe82, 10844 }, /* dead_e */ + { 0x0000fe83, 10851 }, /* dead_E */ + { 0x0000fe50, 10858 }, /* dead_grave */ + { 0x0000fe8c, 10869 }, /* dead_greek */ + { 0x0000fe61, 10880 }, /* dead_hook */ + { 0x0000fe62, 10890 }, /* dead_horn */ + { 0x0000fe84, 10900 }, /* dead_i */ + { 0x0000fe85, 10907 }, /* dead_I */ + { 0x0000fe6d, 10914 }, /* dead_invertedbreve */ + { 0x0000fe5d, 10933 }, /* dead_iota */ + { 0x0000fe93, 10943 }, /* dead_longsolidusoverlay */ + { 0x0000fe90, 10967 }, /* dead_lowline */ + { 0x0000fe54, 10980 }, /* dead_macron */ + { 0x0000fe86, 10992 }, /* dead_o */ + { 0x0000fe87, 10999 }, /* dead_O */ + { 0x0000fe5c, 11006 }, /* dead_ogonek */ + { 0x0000fe53, 11018 }, /* dead_perispomeni */ + { 0x0000fe64, 11035 }, /* dead_psili */ + { 0x0000fe5f, 11046 }, /* dead_semivoiced_sound */ + { 0x0000fe8a, 11068 }, /* dead_small_schwa */ + { 0x0000fe63, 11085 }, /* dead_stroke */ + { 0x0000fe53, 11097 }, /* dead_tilde */ + { 0x0000fe88, 11108 }, /* dead_u */ + { 0x0000fe89, 11115 }, /* dead_U */ + { 0x0000fe5e, 11122 }, /* dead_voiced_sound */ + { 0x00000abd, 11140 }, /* decimalpoint */ + { 0x000000b0, 11153 }, /* degree */ + { 0x0000ffff, 11160 }, /* Delete */ + { 0x1000ff73, 11167 }, /* DeleteChar */ + { 0x1000ff71, 11178 }, /* DeleteLine */ + { 0x1000fe60, 11189 }, /* Dgrave_accent */ + { 0x000000a8, 11203 }, /* diaeresis */ + { 0x00000aed, 11213 }, /* diamond */ + { 0x00000aa5, 11221 }, /* digitspace */ + { 0x0100222c, 11232 }, /* dintegral */ + { 0x000000f7, 11242 }, /* division */ + { 0x00000024, 11251 }, /* dollar */ + { 0x010020ab, 11258 }, /* DongSign */ + { 0x00000aaf, 11267 }, /* doubbaselinedot */ + { 0x000001bd, 11283 }, /* doubleacute */ + { 0x00000af2, 11295 }, /* doubledagger */ + { 0x00000afe, 11308 }, /* doublelowquotemark */ + { 0x0000ff54, 11327 }, /* Down */ + { 0x000008fe, 11332 }, /* downarrow */ + { 0x00000ba8, 11342 }, /* downcaret */ + { 0x00000bd6, 11352 }, /* downshoe */ + { 0x00000bc4, 11361 }, /* downstile */ + { 0x00000bc2, 11371 }, /* downtack */ + { 0x1000ff00, 11380 }, /* DRemove */ + { 0x1000feb0, 11388 }, /* Dring_accent */ + { 0x000001d0, 11401 }, /* Dstroke */ + { 0x000001f0, 11409 }, /* dstroke */ + { 0x1000fe7e, 11417 }, /* Dtilde */ + { 0x00000045, 11424 }, /* E */ + { 0x00000065, 11426 }, /* e */ + { 0x000003cc, 11428 }, /* Eabovedot */ + { 0x000003ec, 11438 }, /* eabovedot */ + { 0x000000c9, 11448 }, /* Eacute */ + { 0x000000e9, 11455 }, /* eacute */ + { 0x01001eb8, 11462 }, /* Ebelowdot */ + { 0x01001eb9, 11472 }, /* ebelowdot */ + { 0x000001cc, 11482 }, /* Ecaron */ + { 0x000001ec, 11489 }, /* ecaron */ + { 0x000000ca, 11496 }, /* Ecircumflex */ + { 0x000000ea, 11508 }, /* ecircumflex */ + { 0x01001ebe, 11520 }, /* Ecircumflexacute */ + { 0x01001ebf, 11537 }, /* ecircumflexacute */ + { 0x01001ec6, 11554 }, /* Ecircumflexbelowdot */ + { 0x01001ec7, 11574 }, /* ecircumflexbelowdot */ + { 0x01001ec0, 11594 }, /* Ecircumflexgrave */ + { 0x01001ec1, 11611 }, /* ecircumflexgrave */ + { 0x01001ec2, 11628 }, /* Ecircumflexhook */ + { 0x01001ec3, 11644 }, /* ecircumflexhook */ + { 0x01001ec4, 11660 }, /* Ecircumflextilde */ + { 0x01001ec5, 11677 }, /* ecircumflextilde */ + { 0x010020a0, 11694 }, /* EcuSign */ + { 0x000000cb, 11702 }, /* Ediaeresis */ + { 0x000000eb, 11713 }, /* ediaeresis */ + { 0x000000c8, 11724 }, /* Egrave */ + { 0x000000e8, 11731 }, /* egrave */ + { 0x01001eba, 11738 }, /* Ehook */ + { 0x01001ebb, 11744 }, /* ehook */ + { 0x01002088, 11750 }, /* eightsubscript */ + { 0x01002078, 11765 }, /* eightsuperior */ + { 0x0000ff2f, 11779 }, /* Eisu_Shift */ + { 0x0000ff30, 11790 }, /* Eisu_toggle */ + { 0x01002208, 11802 }, /* elementof */ + { 0x00000aae, 11812 }, /* ellipsis */ + { 0x00000aa3, 11821 }, /* em3space */ + { 0x00000aa4, 11830 }, /* em4space */ + { 0x000003aa, 11839 }, /* Emacron */ + { 0x000003ba, 11847 }, /* emacron */ + { 0x00000aa9, 11855 }, /* emdash */ + { 0x00000ade, 11862 }, /* emfilledcircle */ + { 0x00000adf, 11877 }, /* emfilledrect */ + { 0x00000ace, 11890 }, /* emopencircle */ + { 0x00000acf, 11903 }, /* emopenrectangle */ + { 0x01002205, 11919 }, /* emptyset */ + { 0x00000aa1, 11928 }, /* emspace */ + { 0x0000ff57, 11936 }, /* End */ + { 0x00000aaa, 11940 }, /* endash */ + { 0x00000ae6, 11947 }, /* enfilledcircbullet */ + { 0x00000ae7, 11966 }, /* enfilledsqbullet */ + { 0x000003bd, 11983 }, /* ENG */ + { 0x000003bf, 11987 }, /* eng */ + { 0x00000ae0, 11991 }, /* enopencircbullet */ + { 0x00000ae1, 12008 }, /* enopensquarebullet */ + { 0x00000aa2, 12027 }, /* enspace */ + { 0x000001ca, 12035 }, /* Eogonek */ + { 0x000001ea, 12043 }, /* eogonek */ + { 0x0000003d, 12051 }, /* equal */ + { 0x0000ff1b, 12057 }, /* Escape */ + { 0x000000d0, 12064 }, /* ETH */ + { 0x000000d0, 12068 }, /* Eth */ + { 0x000000f0, 12072 }, /* eth */ + { 0x01001ebc, 12076 }, /* Etilde */ + { 0x01001ebd, 12083 }, /* etilde */ + { 0x000020ac, 12090 }, /* EuroSign */ + { 0x00000021, 12099 }, /* exclam */ + { 0x000000a1, 12106 }, /* exclamdown */ + { 0x0000ff62, 12117 }, /* Execute */ + { 0x1000ff76, 12125 }, /* Ext16bit_L */ + { 0x1000ff77, 12136 }, /* Ext16bit_R */ + { 0x010001b7, 12147 }, /* EZH */ + { 0x01000292, 12151 }, /* ezh */ + { 0x00000046, 12155 }, /* F */ + { 0x00000066, 12157 }, /* f */ + { 0x0000ffbe, 12159 }, /* F1 */ + { 0x0000ffc7, 12162 }, /* F10 */ + { 0x0000ffc8, 12166 }, /* F11 */ + { 0x0000ffc9, 12170 }, /* F12 */ + { 0x0000ffca, 12174 }, /* F13 */ + { 0x0000ffcb, 12178 }, /* F14 */ + { 0x0000ffcc, 12182 }, /* F15 */ + { 0x0000ffcd, 12186 }, /* F16 */ + { 0x0000ffce, 12190 }, /* F17 */ + { 0x0000ffcf, 12194 }, /* F18 */ + { 0x0000ffd0, 12198 }, /* F19 */ + { 0x0000ffbf, 12202 }, /* F2 */ + { 0x0000ffd1, 12205 }, /* F20 */ + { 0x0000ffd2, 12209 }, /* F21 */ + { 0x0000ffd3, 12213 }, /* F22 */ + { 0x0000ffd4, 12217 }, /* F23 */ + { 0x0000ffd5, 12221 }, /* F24 */ + { 0x0000ffd6, 12225 }, /* F25 */ + { 0x0000ffd7, 12229 }, /* F26 */ + { 0x0000ffd8, 12233 }, /* F27 */ + { 0x0000ffd9, 12237 }, /* F28 */ + { 0x0000ffda, 12241 }, /* F29 */ + { 0x0000ffc0, 12245 }, /* F3 */ + { 0x0000ffdb, 12248 }, /* F30 */ + { 0x0000ffdc, 12252 }, /* F31 */ + { 0x0000ffdd, 12256 }, /* F32 */ + { 0x0000ffde, 12260 }, /* F33 */ + { 0x0000ffdf, 12264 }, /* F34 */ + { 0x0000ffe0, 12268 }, /* F35 */ + { 0x0000ffc1, 12272 }, /* F4 */ + { 0x0000ffc2, 12275 }, /* F5 */ + { 0x0000ffc3, 12278 }, /* F6 */ + { 0x0000ffc4, 12281 }, /* F7 */ + { 0x0000ffc5, 12284 }, /* F8 */ + { 0x0000ffc6, 12287 }, /* F9 */ + { 0x01001e1e, 12290 }, /* Fabovedot */ + { 0x01001e1f, 12300 }, /* fabovedot */ + { 0x010006f0, 12310 }, /* Farsi_0 */ + { 0x010006f1, 12318 }, /* Farsi_1 */ + { 0x010006f2, 12326 }, /* Farsi_2 */ + { 0x010006f3, 12334 }, /* Farsi_3 */ + { 0x010006f4, 12342 }, /* Farsi_4 */ + { 0x010006f5, 12350 }, /* Farsi_5 */ + { 0x010006f6, 12358 }, /* Farsi_6 */ + { 0x010006f7, 12366 }, /* Farsi_7 */ + { 0x010006f8, 12374 }, /* Farsi_8 */ + { 0x010006f9, 12382 }, /* Farsi_9 */ + { 0x010006cc, 12390 }, /* Farsi_yeh */ + { 0x00000af8, 12400 }, /* femalesymbol */ + { 0x000009e3, 12413 }, /* ff */ + { 0x010020a3, 12416 }, /* FFrancSign */ + { 0x00000abb, 12427 }, /* figdash */ + { 0x00000adc, 12435 }, /* filledlefttribullet */ + { 0x00000adb, 12455 }, /* filledrectbullet */ + { 0x00000add, 12472 }, /* filledrighttribullet */ + { 0x00000ae9, 12493 }, /* filledtribulletdown */ + { 0x00000ae8, 12513 }, /* filledtribulletup */ + { 0x0000ff68, 12531 }, /* Find */ + { 0x0000fed0, 12536 }, /* First_Virtual_Screen */ + { 0x00000ac5, 12557 }, /* fiveeighths */ + { 0x00000ab7, 12569 }, /* fivesixths */ + { 0x01002085, 12580 }, /* fivesubscript */ + { 0x01002075, 12594 }, /* fivesuperior */ + { 0x00000ab5, 12607 }, /* fourfifths */ + { 0x01002084, 12618 }, /* foursubscript */ + { 0x01002074, 12632 }, /* foursuperior */ + { 0x0100221c, 12645 }, /* fourthroot */ + { 0x000008f6, 12656 }, /* function */ + { 0x00000047, 12665 }, /* G */ + { 0x00000067, 12667 }, /* g */ + { 0x000002d5, 12669 }, /* Gabovedot */ + { 0x000002f5, 12679 }, /* gabovedot */ + { 0x000002ab, 12689 }, /* Gbreve */ + { 0x000002bb, 12696 }, /* gbreve */ + { 0x010001e6, 12703 }, /* Gcaron */ + { 0x010001e7, 12710 }, /* gcaron */ + { 0x000003ab, 12717 }, /* Gcedilla */ + { 0x000003bb, 12726 }, /* gcedilla */ + { 0x000002d8, 12735 }, /* Gcircumflex */ + { 0x000002f8, 12747 }, /* gcircumflex */ + { 0x010010d0, 12759 }, /* Georgian_an */ + { 0x010010d1, 12771 }, /* Georgian_ban */ + { 0x010010ea, 12784 }, /* Georgian_can */ + { 0x010010ed, 12797 }, /* Georgian_char */ + { 0x010010e9, 12811 }, /* Georgian_chin */ + { 0x010010ec, 12825 }, /* Georgian_cil */ + { 0x010010d3, 12838 }, /* Georgian_don */ + { 0x010010d4, 12851 }, /* Georgian_en */ + { 0x010010f6, 12863 }, /* Georgian_fi */ + { 0x010010d2, 12875 }, /* Georgian_gan */ + { 0x010010e6, 12888 }, /* Georgian_ghan */ + { 0x010010f0, 12902 }, /* Georgian_hae */ + { 0x010010f4, 12915 }, /* Georgian_har */ + { 0x010010f1, 12928 }, /* Georgian_he */ + { 0x010010f2, 12940 }, /* Georgian_hie */ + { 0x010010f5, 12953 }, /* Georgian_hoe */ + { 0x010010d8, 12966 }, /* Georgian_in */ + { 0x010010ef, 12978 }, /* Georgian_jhan */ + { 0x010010eb, 12992 }, /* Georgian_jil */ + { 0x010010d9, 13005 }, /* Georgian_kan */ + { 0x010010e5, 13018 }, /* Georgian_khar */ + { 0x010010da, 13032 }, /* Georgian_las */ + { 0x010010db, 13045 }, /* Georgian_man */ + { 0x010010dc, 13058 }, /* Georgian_nar */ + { 0x010010dd, 13071 }, /* Georgian_on */ + { 0x010010de, 13083 }, /* Georgian_par */ + { 0x010010e4, 13096 }, /* Georgian_phar */ + { 0x010010e7, 13110 }, /* Georgian_qar */ + { 0x010010e0, 13123 }, /* Georgian_rae */ + { 0x010010e1, 13136 }, /* Georgian_san */ + { 0x010010e8, 13149 }, /* Georgian_shin */ + { 0x010010d7, 13163 }, /* Georgian_tan */ + { 0x010010e2, 13176 }, /* Georgian_tar */ + { 0x010010e3, 13189 }, /* Georgian_un */ + { 0x010010d5, 13201 }, /* Georgian_vin */ + { 0x010010f3, 13214 }, /* Georgian_we */ + { 0x010010ee, 13226 }, /* Georgian_xan */ + { 0x010010d6, 13239 }, /* Georgian_zen */ + { 0x010010df, 13252 }, /* Georgian_zhar */ + { 0x00000060, 13266 }, /* grave */ + { 0x0000003e, 13272 }, /* greater */ + { 0x000008be, 13280 }, /* greaterthanequal */ + { 0x000007ae, 13297 }, /* Greek_accentdieresis */ + { 0x000007c1, 13318 }, /* Greek_ALPHA */ + { 0x000007e1, 13330 }, /* Greek_alpha */ + { 0x000007a1, 13342 }, /* Greek_ALPHAaccent */ + { 0x000007b1, 13360 }, /* Greek_alphaaccent */ + { 0x000007c2, 13378 }, /* Greek_BETA */ + { 0x000007e2, 13389 }, /* Greek_beta */ + { 0x000007d7, 13400 }, /* Greek_CHI */ + { 0x000007f7, 13410 }, /* Greek_chi */ + { 0x000007c4, 13420 }, /* Greek_DELTA */ + { 0x000007e4, 13432 }, /* Greek_delta */ + { 0x000007c5, 13444 }, /* Greek_EPSILON */ + { 0x000007e5, 13458 }, /* Greek_epsilon */ + { 0x000007a2, 13472 }, /* Greek_EPSILONaccent */ + { 0x000007b2, 13492 }, /* Greek_epsilonaccent */ + { 0x000007c7, 13512 }, /* Greek_ETA */ + { 0x000007e7, 13522 }, /* Greek_eta */ + { 0x000007a3, 13532 }, /* Greek_ETAaccent */ + { 0x000007b3, 13548 }, /* Greek_etaaccent */ + { 0x000007f3, 13564 }, /* Greek_finalsmallsigma */ + { 0x000007c3, 13586 }, /* Greek_GAMMA */ + { 0x000007e3, 13598 }, /* Greek_gamma */ + { 0x000007af, 13610 }, /* Greek_horizbar */ + { 0x000007c9, 13625 }, /* Greek_IOTA */ + { 0x000007e9, 13636 }, /* Greek_iota */ + { 0x000007a4, 13647 }, /* Greek_IOTAaccent */ + { 0x000007b4, 13664 }, /* Greek_iotaaccent */ + { 0x000007b6, 13681 }, /* Greek_iotaaccentdieresis */ + { 0x000007a5, 13706 }, /* Greek_IOTAdiaeresis */ + { 0x000007a5, 13726 }, /* Greek_IOTAdieresis */ + { 0x000007b5, 13745 }, /* Greek_iotadieresis */ + { 0x000007ca, 13764 }, /* Greek_KAPPA */ + { 0x000007ea, 13776 }, /* Greek_kappa */ + { 0x000007cb, 13788 }, /* Greek_LAMBDA */ + { 0x000007eb, 13801 }, /* Greek_lambda */ + { 0x000007cb, 13814 }, /* Greek_LAMDA */ + { 0x000007eb, 13826 }, /* Greek_lamda */ + { 0x000007cc, 13838 }, /* Greek_MU */ + { 0x000007ec, 13847 }, /* Greek_mu */ + { 0x000007cd, 13856 }, /* Greek_NU */ + { 0x000007ed, 13865 }, /* Greek_nu */ + { 0x000007d9, 13874 }, /* Greek_OMEGA */ + { 0x000007f9, 13886 }, /* Greek_omega */ + { 0x000007ab, 13898 }, /* Greek_OMEGAaccent */ + { 0x000007bb, 13916 }, /* Greek_omegaaccent */ + { 0x000007cf, 13934 }, /* Greek_OMICRON */ + { 0x000007ef, 13948 }, /* Greek_omicron */ + { 0x000007a7, 13962 }, /* Greek_OMICRONaccent */ + { 0x000007b7, 13982 }, /* Greek_omicronaccent */ + { 0x000007d6, 14002 }, /* Greek_PHI */ + { 0x000007f6, 14012 }, /* Greek_phi */ + { 0x000007d0, 14022 }, /* Greek_PI */ + { 0x000007f0, 14031 }, /* Greek_pi */ + { 0x000007d8, 14040 }, /* Greek_PSI */ + { 0x000007f8, 14050 }, /* Greek_psi */ + { 0x000007d1, 14060 }, /* Greek_RHO */ + { 0x000007f1, 14070 }, /* Greek_rho */ + { 0x000007d2, 14080 }, /* Greek_SIGMA */ + { 0x000007f2, 14092 }, /* Greek_sigma */ + { 0x0000ff7e, 14104 }, /* Greek_switch */ + { 0x000007d4, 14117 }, /* Greek_TAU */ + { 0x000007f4, 14127 }, /* Greek_tau */ + { 0x000007c8, 14137 }, /* Greek_THETA */ + { 0x000007e8, 14149 }, /* Greek_theta */ + { 0x000007d5, 14161 }, /* Greek_UPSILON */ + { 0x000007f5, 14175 }, /* Greek_upsilon */ + { 0x000007a8, 14189 }, /* Greek_UPSILONaccent */ + { 0x000007b8, 14209 }, /* Greek_upsilonaccent */ + { 0x000007ba, 14229 }, /* Greek_upsilonaccentdieresis */ + { 0x000007a9, 14257 }, /* Greek_UPSILONdieresis */ + { 0x000007b9, 14279 }, /* Greek_upsilondieresis */ + { 0x000007ce, 14301 }, /* Greek_XI */ + { 0x000007ee, 14310 }, /* Greek_xi */ + { 0x000007c6, 14319 }, /* Greek_ZETA */ + { 0x000007e6, 14330 }, /* Greek_zeta */ + { 0x100000be, 14341 }, /* guilder */ + { 0x000000ab, 14349 }, /* guillemotleft */ + { 0x000000bb, 14363 }, /* guillemotright */ + { 0x00000048, 14378 }, /* H */ + { 0x00000068, 14380 }, /* h */ + { 0x00000aa8, 14382 }, /* hairspace */ + { 0x0000ff31, 14392 }, /* Hangul */ + { 0x00000ebf, 14399 }, /* Hangul_A */ + { 0x00000ec0, 14408 }, /* Hangul_AE */ + { 0x00000ef6, 14418 }, /* Hangul_AraeA */ + { 0x00000ef7, 14431 }, /* Hangul_AraeAE */ + { 0x0000ff39, 14445 }, /* Hangul_Banja */ + { 0x00000eba, 14458 }, /* Hangul_Cieuc */ + { 0x0000ff37, 14471 }, /* Hangul_Codeinput */ + { 0x00000ea7, 14488 }, /* Hangul_Dikeud */ + { 0x00000ec4, 14502 }, /* Hangul_E */ + { 0x0000ff33, 14511 }, /* Hangul_End */ + { 0x00000ec3, 14522 }, /* Hangul_EO */ + { 0x00000ed1, 14532 }, /* Hangul_EU */ + { 0x0000ff34, 14542 }, /* Hangul_Hanja */ + { 0x00000ebe, 14555 }, /* Hangul_Hieuh */ + { 0x00000ed3, 14568 }, /* Hangul_I */ + { 0x00000eb7, 14577 }, /* Hangul_Ieung */ + { 0x00000eea, 14590 }, /* Hangul_J_Cieuc */ + { 0x00000eda, 14605 }, /* Hangul_J_Dikeud */ + { 0x00000eee, 14621 }, /* Hangul_J_Hieuh */ + { 0x00000ee8, 14636 }, /* Hangul_J_Ieung */ + { 0x00000ee9, 14651 }, /* Hangul_J_Jieuj */ + { 0x00000eeb, 14666 }, /* Hangul_J_Khieuq */ + { 0x00000ed4, 14682 }, /* Hangul_J_Kiyeog */ + { 0x00000ed6, 14698 }, /* Hangul_J_KiyeogSios */ + { 0x00000ef9, 14718 }, /* Hangul_J_KkogjiDalrinIeung */ + { 0x00000ee3, 14745 }, /* Hangul_J_Mieum */ + { 0x00000ed7, 14760 }, /* Hangul_J_Nieun */ + { 0x00000ed9, 14775 }, /* Hangul_J_NieunHieuh */ + { 0x00000ed8, 14795 }, /* Hangul_J_NieunJieuj */ + { 0x00000ef8, 14815 }, /* Hangul_J_PanSios */ + { 0x00000eed, 14832 }, /* Hangul_J_Phieuf */ + { 0x00000ee4, 14848 }, /* Hangul_J_Pieub */ + { 0x00000ee5, 14863 }, /* Hangul_J_PieubSios */ + { 0x00000edb, 14882 }, /* Hangul_J_Rieul */ + { 0x00000ee2, 14897 }, /* Hangul_J_RieulHieuh */ + { 0x00000edc, 14917 }, /* Hangul_J_RieulKiyeog */ + { 0x00000edd, 14938 }, /* Hangul_J_RieulMieum */ + { 0x00000ee1, 14958 }, /* Hangul_J_RieulPhieuf */ + { 0x00000ede, 14979 }, /* Hangul_J_RieulPieub */ + { 0x00000edf, 14999 }, /* Hangul_J_RieulSios */ + { 0x00000ee0, 15018 }, /* Hangul_J_RieulTieut */ + { 0x00000ee6, 15038 }, /* Hangul_J_Sios */ + { 0x00000ed5, 15052 }, /* Hangul_J_SsangKiyeog */ + { 0x00000ee7, 15073 }, /* Hangul_J_SsangSios */ + { 0x00000eec, 15092 }, /* Hangul_J_Tieut */ + { 0x00000efa, 15107 }, /* Hangul_J_YeorinHieuh */ + { 0x0000ff35, 15128 }, /* Hangul_Jamo */ + { 0x0000ff38, 15140 }, /* Hangul_Jeonja */ + { 0x00000eb8, 15154 }, /* Hangul_Jieuj */ + { 0x00000ebb, 15167 }, /* Hangul_Khieuq */ + { 0x00000ea1, 15181 }, /* Hangul_Kiyeog */ + { 0x00000ea3, 15195 }, /* Hangul_KiyeogSios */ + { 0x00000ef3, 15213 }, /* Hangul_KkogjiDalrinIeung */ + { 0x00000eb1, 15238 }, /* Hangul_Mieum */ + { 0x0000ff3d, 15251 }, /* Hangul_MultipleCandidate */ + { 0x00000ea4, 15276 }, /* Hangul_Nieun */ + { 0x00000ea6, 15289 }, /* Hangul_NieunHieuh */ + { 0x00000ea5, 15307 }, /* Hangul_NieunJieuj */ + { 0x00000ec7, 15325 }, /* Hangul_O */ + { 0x00000eca, 15334 }, /* Hangul_OE */ + { 0x00000ef2, 15344 }, /* Hangul_PanSios */ + { 0x00000ebd, 15359 }, /* Hangul_Phieuf */ + { 0x00000eb2, 15373 }, /* Hangul_Pieub */ + { 0x00000eb4, 15386 }, /* Hangul_PieubSios */ + { 0x0000ff3b, 15403 }, /* Hangul_PostHanja */ + { 0x0000ff3a, 15420 }, /* Hangul_PreHanja */ + { 0x0000ff3e, 15436 }, /* Hangul_PreviousCandidate */ + { 0x00000ea9, 15461 }, /* Hangul_Rieul */ + { 0x00000eb0, 15474 }, /* Hangul_RieulHieuh */ + { 0x00000eaa, 15492 }, /* Hangul_RieulKiyeog */ + { 0x00000eab, 15511 }, /* Hangul_RieulMieum */ + { 0x00000eaf, 15529 }, /* Hangul_RieulPhieuf */ + { 0x00000eac, 15548 }, /* Hangul_RieulPieub */ + { 0x00000ead, 15566 }, /* Hangul_RieulSios */ + { 0x00000eae, 15583 }, /* Hangul_RieulTieut */ + { 0x00000eef, 15601 }, /* Hangul_RieulYeorinHieuh */ + { 0x0000ff36, 15625 }, /* Hangul_Romaja */ + { 0x0000ff3c, 15639 }, /* Hangul_SingleCandidate */ + { 0x00000eb5, 15662 }, /* Hangul_Sios */ + { 0x0000ff3f, 15674 }, /* Hangul_Special */ + { 0x00000ea8, 15689 }, /* Hangul_SsangDikeud */ + { 0x00000eb9, 15708 }, /* Hangul_SsangJieuj */ + { 0x00000ea2, 15726 }, /* Hangul_SsangKiyeog */ + { 0x00000eb3, 15745 }, /* Hangul_SsangPieub */ + { 0x00000eb6, 15763 }, /* Hangul_SsangSios */ + { 0x0000ff32, 15780 }, /* Hangul_Start */ + { 0x00000ef0, 15793 }, /* Hangul_SunkyeongeumMieum */ + { 0x00000ef4, 15818 }, /* Hangul_SunkyeongeumPhieuf */ + { 0x00000ef1, 15844 }, /* Hangul_SunkyeongeumPieub */ + { 0x0000ff7e, 15869 }, /* Hangul_switch */ + { 0x00000ebc, 15883 }, /* Hangul_Tieut */ + { 0x00000ecc, 15896 }, /* Hangul_U */ + { 0x00000ec8, 15905 }, /* Hangul_WA */ + { 0x00000ec9, 15915 }, /* Hangul_WAE */ + { 0x00000ece, 15926 }, /* Hangul_WE */ + { 0x00000ecd, 15936 }, /* Hangul_WEO */ + { 0x00000ecf, 15947 }, /* Hangul_WI */ + { 0x00000ec1, 15957 }, /* Hangul_YA */ + { 0x00000ec2, 15967 }, /* Hangul_YAE */ + { 0x00000ec6, 15978 }, /* Hangul_YE */ + { 0x00000ec5, 15988 }, /* Hangul_YEO */ + { 0x00000ef5, 15999 }, /* Hangul_YeorinHieuh */ + { 0x00000ed2, 16018 }, /* Hangul_YI */ + { 0x00000ecb, 16028 }, /* Hangul_YO */ + { 0x00000ed0, 16038 }, /* Hangul_YU */ + { 0x0000ff29, 16048 }, /* Hankaku */ + { 0x000002a6, 16056 }, /* Hcircumflex */ + { 0x000002b6, 16068 }, /* hcircumflex */ + { 0x00000aee, 16080 }, /* heart */ + { 0x00000ce0, 16086 }, /* hebrew_aleph */ + { 0x00000cf2, 16099 }, /* hebrew_ayin */ + { 0x00000ce1, 16111 }, /* hebrew_bet */ + { 0x00000ce1, 16122 }, /* hebrew_beth */ + { 0x00000ce7, 16134 }, /* hebrew_chet */ + { 0x00000ce3, 16146 }, /* hebrew_dalet */ + { 0x00000ce3, 16159 }, /* hebrew_daleth */ + { 0x00000cdf, 16173 }, /* hebrew_doublelowline */ + { 0x00000cea, 16194 }, /* hebrew_finalkaph */ + { 0x00000ced, 16211 }, /* hebrew_finalmem */ + { 0x00000cef, 16227 }, /* hebrew_finalnun */ + { 0x00000cf3, 16243 }, /* hebrew_finalpe */ + { 0x00000cf5, 16258 }, /* hebrew_finalzade */ + { 0x00000cf5, 16275 }, /* hebrew_finalzadi */ + { 0x00000ce2, 16292 }, /* hebrew_gimel */ + { 0x00000ce2, 16305 }, /* hebrew_gimmel */ + { 0x00000ce4, 16319 }, /* hebrew_he */ + { 0x00000ce7, 16329 }, /* hebrew_het */ + { 0x00000ceb, 16340 }, /* hebrew_kaph */ + { 0x00000cf7, 16352 }, /* hebrew_kuf */ + { 0x00000cec, 16363 }, /* hebrew_lamed */ + { 0x00000cee, 16376 }, /* hebrew_mem */ + { 0x00000cf0, 16387 }, /* hebrew_nun */ + { 0x00000cf4, 16398 }, /* hebrew_pe */ + { 0x00000cf7, 16408 }, /* hebrew_qoph */ + { 0x00000cf8, 16420 }, /* hebrew_resh */ + { 0x00000cf1, 16432 }, /* hebrew_samech */ + { 0x00000cf1, 16446 }, /* hebrew_samekh */ + { 0x00000cf9, 16460 }, /* hebrew_shin */ + { 0x0000ff7e, 16472 }, /* Hebrew_switch */ + { 0x00000cfa, 16486 }, /* hebrew_taf */ + { 0x00000cfa, 16497 }, /* hebrew_taw */ + { 0x00000ce8, 16508 }, /* hebrew_tet */ + { 0x00000ce8, 16519 }, /* hebrew_teth */ + { 0x00000ce5, 16531 }, /* hebrew_waw */ + { 0x00000ce9, 16542 }, /* hebrew_yod */ + { 0x00000cf6, 16553 }, /* hebrew_zade */ + { 0x00000cf6, 16565 }, /* hebrew_zadi */ + { 0x00000ce6, 16577 }, /* hebrew_zain */ + { 0x00000ce6, 16589 }, /* hebrew_zayin */ + { 0x0000ff6a, 16602 }, /* Help */ + { 0x0000ff23, 16607 }, /* Henkan */ + { 0x0000ff23, 16614 }, /* Henkan_Mode */ + { 0x00000ada, 16626 }, /* hexagram */ + { 0x0000ff25, 16635 }, /* Hiragana */ + { 0x0000ff27, 16644 }, /* Hiragana_Katakana */ + { 0x0000ff50, 16662 }, /* Home */ + { 0x000008a3, 16667 }, /* horizconnector */ + { 0x000009ef, 16682 }, /* horizlinescan1 */ + { 0x000009f0, 16697 }, /* horizlinescan3 */ + { 0x000009f1, 16712 }, /* horizlinescan5 */ + { 0x000009f2, 16727 }, /* horizlinescan7 */ + { 0x000009f3, 16742 }, /* horizlinescan9 */ + { 0x1000ff74, 16757 }, /* hpBackTab */ + { 0x100000fc, 16767 }, /* hpblock */ + { 0x1000ff6f, 16775 }, /* hpClearLine */ + { 0x1000ff73, 16787 }, /* hpDeleteChar */ + { 0x1000ff71, 16800 }, /* hpDeleteLine */ + { 0x100000be, 16813 }, /* hpguilder */ + { 0x1000ff72, 16823 }, /* hpInsertChar */ + { 0x1000ff70, 16836 }, /* hpInsertLine */ + { 0x100000ee, 16849 }, /* hpIO */ + { 0x1000ff75, 16854 }, /* hpKP_BackTab */ + { 0x100000af, 16867 }, /* hplira */ + { 0x100000f6, 16874 }, /* hplongminus */ + { 0x1000ff48, 16886 }, /* hpModelock1 */ + { 0x1000ff49, 16898 }, /* hpModelock2 */ + { 0x100000a8, 16910 }, /* hpmute_acute */ + { 0x100000aa, 16923 }, /* hpmute_asciicircum */ + { 0x100000ac, 16942 }, /* hpmute_asciitilde */ + { 0x100000ab, 16960 }, /* hpmute_diaeresis */ + { 0x100000a9, 16977 }, /* hpmute_grave */ + { 0x1000ff6c, 16990 }, /* hpReset */ + { 0x1000ff6d, 16998 }, /* hpSystem */ + { 0x1000ff6e, 17007 }, /* hpUser */ + { 0x100000ee, 17014 }, /* hpYdiaeresis */ + { 0x000002a1, 17027 }, /* Hstroke */ + { 0x000002b1, 17035 }, /* hstroke */ + { 0x000009e2, 17043 }, /* ht */ + { 0x0000ffed, 17046 }, /* Hyper_L */ + { 0x0000ffee, 17054 }, /* Hyper_R */ + { 0x000000ad, 17062 }, /* hyphen */ + { 0x00000049, 17069 }, /* I */ + { 0x00000069, 17071 }, /* i */ + { 0x000002a9, 17073 }, /* Iabovedot */ + { 0x000000cd, 17083 }, /* Iacute */ + { 0x000000ed, 17090 }, /* iacute */ + { 0x01001eca, 17097 }, /* Ibelowdot */ + { 0x01001ecb, 17107 }, /* ibelowdot */ + { 0x0100012c, 17117 }, /* Ibreve */ + { 0x0100012d, 17124 }, /* ibreve */ + { 0x000000ce, 17131 }, /* Icircumflex */ + { 0x000000ee, 17143 }, /* icircumflex */ + { 0x000008cf, 17155 }, /* identical */ + { 0x000000cf, 17165 }, /* Idiaeresis */ + { 0x000000ef, 17176 }, /* idiaeresis */ + { 0x000002b9, 17187 }, /* idotless */ + { 0x000008cd, 17196 }, /* ifonlyif */ + { 0x000000cc, 17205 }, /* Igrave */ + { 0x000000ec, 17212 }, /* igrave */ + { 0x01001ec8, 17219 }, /* Ihook */ + { 0x01001ec9, 17225 }, /* ihook */ + { 0x000003cf, 17231 }, /* Imacron */ + { 0x000003ef, 17239 }, /* imacron */ + { 0x000008ce, 17247 }, /* implies */ + { 0x000008da, 17255 }, /* includedin */ + { 0x000008db, 17266 }, /* includes */ + { 0x000008c2, 17275 }, /* infinity */ + { 0x0000ff63, 17284 }, /* Insert */ + { 0x1000ff72, 17291 }, /* InsertChar */ + { 0x1000ff70, 17302 }, /* InsertLine */ + { 0x000008bf, 17313 }, /* integral */ + { 0x000008dc, 17322 }, /* intersection */ + { 0x100000ee, 17335 }, /* IO */ + { 0x000003c7, 17338 }, /* Iogonek */ + { 0x000003e7, 17346 }, /* iogonek */ + { 0x0000fe33, 17354 }, /* ISO_Center_Object */ + { 0x0000fe30, 17372 }, /* ISO_Continuous_Underline */ + { 0x0000fe31, 17397 }, /* ISO_Discontinuous_Underline */ + { 0x0000fe32, 17425 }, /* ISO_Emphasize */ + { 0x0000fe34, 17439 }, /* ISO_Enter */ + { 0x0000fe2f, 17449 }, /* ISO_Fast_Cursor_Down */ + { 0x0000fe2c, 17470 }, /* ISO_Fast_Cursor_Left */ + { 0x0000fe2d, 17491 }, /* ISO_Fast_Cursor_Right */ + { 0x0000fe2e, 17513 }, /* ISO_Fast_Cursor_Up */ + { 0x0000fe0c, 17532 }, /* ISO_First_Group */ + { 0x0000fe0d, 17548 }, /* ISO_First_Group_Lock */ + { 0x0000fe06, 17569 }, /* ISO_Group_Latch */ + { 0x0000fe07, 17585 }, /* ISO_Group_Lock */ + { 0x0000ff7e, 17600 }, /* ISO_Group_Shift */ + { 0x0000fe0e, 17616 }, /* ISO_Last_Group */ + { 0x0000fe0f, 17631 }, /* ISO_Last_Group_Lock */ + { 0x0000fe20, 17651 }, /* ISO_Left_Tab */ + { 0x0000fe02, 17664 }, /* ISO_Level2_Latch */ + { 0x0000fe04, 17681 }, /* ISO_Level3_Latch */ + { 0x0000fe05, 17698 }, /* ISO_Level3_Lock */ + { 0x0000fe03, 17714 }, /* ISO_Level3_Shift */ + { 0x0000fe12, 17731 }, /* ISO_Level5_Latch */ + { 0x0000fe13, 17748 }, /* ISO_Level5_Lock */ + { 0x0000fe11, 17764 }, /* ISO_Level5_Shift */ + { 0x0000fe01, 17781 }, /* ISO_Lock */ + { 0x0000fe22, 17790 }, /* ISO_Move_Line_Down */ + { 0x0000fe21, 17809 }, /* ISO_Move_Line_Up */ + { 0x0000fe08, 17826 }, /* ISO_Next_Group */ + { 0x0000fe09, 17841 }, /* ISO_Next_Group_Lock */ + { 0x0000fe24, 17861 }, /* ISO_Partial_Line_Down */ + { 0x0000fe23, 17883 }, /* ISO_Partial_Line_Up */ + { 0x0000fe25, 17903 }, /* ISO_Partial_Space_Left */ + { 0x0000fe26, 17926 }, /* ISO_Partial_Space_Right */ + { 0x0000fe0a, 17950 }, /* ISO_Prev_Group */ + { 0x0000fe0b, 17965 }, /* ISO_Prev_Group_Lock */ + { 0x0000fe2b, 17985 }, /* ISO_Release_Both_Margins */ + { 0x0000fe29, 18010 }, /* ISO_Release_Margin_Left */ + { 0x0000fe2a, 18034 }, /* ISO_Release_Margin_Right */ + { 0x0000fe27, 18059 }, /* ISO_Set_Margin_Left */ + { 0x0000fe28, 18079 }, /* ISO_Set_Margin_Right */ + { 0x000003a5, 18100 }, /* Itilde */ + { 0x000003b5, 18107 }, /* itilde */ + { 0x0000004a, 18114 }, /* J */ + { 0x0000006a, 18116 }, /* j */ + { 0x000002ac, 18118 }, /* Jcircumflex */ + { 0x000002bc, 18130 }, /* jcircumflex */ + { 0x00000bca, 18142 }, /* jot */ + { 0x0000004b, 18146 }, /* K */ + { 0x0000006b, 18148 }, /* k */ + { 0x000004a7, 18150 }, /* kana_a */ + { 0x000004b1, 18157 }, /* kana_A */ + { 0x000004c1, 18164 }, /* kana_CHI */ + { 0x000004a3, 18173 }, /* kana_closingbracket */ + { 0x000004a4, 18193 }, /* kana_comma */ + { 0x000004a5, 18204 }, /* kana_conjunctive */ + { 0x000004aa, 18221 }, /* kana_e */ + { 0x000004b4, 18228 }, /* kana_E */ + { 0x000004cc, 18235 }, /* kana_FU */ + { 0x000004a1, 18243 }, /* kana_fullstop */ + { 0x000004ca, 18257 }, /* kana_HA */ + { 0x000004cd, 18265 }, /* kana_HE */ + { 0x000004cb, 18273 }, /* kana_HI */ + { 0x000004ce, 18281 }, /* kana_HO */ + { 0x000004cc, 18289 }, /* kana_HU */ + { 0x000004a8, 18297 }, /* kana_i */ + { 0x000004b2, 18304 }, /* kana_I */ + { 0x000004b6, 18311 }, /* kana_KA */ + { 0x000004b9, 18319 }, /* kana_KE */ + { 0x000004b7, 18327 }, /* kana_KI */ + { 0x000004ba, 18335 }, /* kana_KO */ + { 0x000004b8, 18343 }, /* kana_KU */ + { 0x0000ff2d, 18351 }, /* Kana_Lock */ + { 0x000004cf, 18361 }, /* kana_MA */ + { 0x000004d2, 18369 }, /* kana_ME */ + { 0x000004d0, 18377 }, /* kana_MI */ + { 0x000004a5, 18385 }, /* kana_middledot */ + { 0x000004d3, 18400 }, /* kana_MO */ + { 0x000004d1, 18408 }, /* kana_MU */ + { 0x000004dd, 18416 }, /* kana_N */ + { 0x000004c5, 18423 }, /* kana_NA */ + { 0x000004c8, 18431 }, /* kana_NE */ + { 0x000004c6, 18439 }, /* kana_NI */ + { 0x000004c9, 18447 }, /* kana_NO */ + { 0x000004c7, 18455 }, /* kana_NU */ + { 0x000004ab, 18463 }, /* kana_o */ + { 0x000004b5, 18470 }, /* kana_O */ + { 0x000004a2, 18477 }, /* kana_openingbracket */ + { 0x000004d7, 18497 }, /* kana_RA */ + { 0x000004da, 18505 }, /* kana_RE */ + { 0x000004d8, 18513 }, /* kana_RI */ + { 0x000004db, 18521 }, /* kana_RO */ + { 0x000004d9, 18529 }, /* kana_RU */ + { 0x000004bb, 18537 }, /* kana_SA */ + { 0x000004be, 18545 }, /* kana_SE */ + { 0x000004bc, 18553 }, /* kana_SHI */ + { 0x0000ff2e, 18562 }, /* Kana_Shift */ + { 0x000004bf, 18573 }, /* kana_SO */ + { 0x000004bd, 18581 }, /* kana_SU */ + { 0x0000ff7e, 18589 }, /* kana_switch */ + { 0x000004c0, 18601 }, /* kana_TA */ + { 0x000004c3, 18609 }, /* kana_TE */ + { 0x000004c1, 18617 }, /* kana_TI */ + { 0x000004c4, 18625 }, /* kana_TO */ + { 0x000004af, 18633 }, /* kana_tsu */ + { 0x000004c2, 18642 }, /* kana_TSU */ + { 0x000004af, 18651 }, /* kana_tu */ + { 0x000004c2, 18659 }, /* kana_TU */ + { 0x000004a9, 18667 }, /* kana_u */ + { 0x000004b3, 18674 }, /* kana_U */ + { 0x000004dc, 18681 }, /* kana_WA */ + { 0x000004a6, 18689 }, /* kana_WO */ + { 0x000004ac, 18697 }, /* kana_ya */ + { 0x000004d4, 18705 }, /* kana_YA */ + { 0x000004ae, 18713 }, /* kana_yo */ + { 0x000004d6, 18721 }, /* kana_YO */ + { 0x000004ad, 18729 }, /* kana_yu */ + { 0x000004d5, 18737 }, /* kana_YU */ + { 0x0000ff21, 18745 }, /* Kanji */ + { 0x0000ff37, 18751 }, /* Kanji_Bangou */ + { 0x000003a2, 18764 }, /* kappa */ + { 0x0000ff26, 18770 }, /* Katakana */ + { 0x000003d3, 18779 }, /* Kcedilla */ + { 0x000003f3, 18788 }, /* kcedilla */ + { 0x00000eff, 18797 }, /* Korean_Won */ + { 0x0000ffb0, 18808 }, /* KP_0 */ + { 0x0000ffb1, 18813 }, /* KP_1 */ + { 0x0000ffb2, 18818 }, /* KP_2 */ + { 0x0000ffb3, 18823 }, /* KP_3 */ + { 0x0000ffb4, 18828 }, /* KP_4 */ + { 0x0000ffb5, 18833 }, /* KP_5 */ + { 0x0000ffb6, 18838 }, /* KP_6 */ + { 0x0000ffb7, 18843 }, /* KP_7 */ + { 0x0000ffb8, 18848 }, /* KP_8 */ + { 0x0000ffb9, 18853 }, /* KP_9 */ + { 0x0000ffab, 18858 }, /* KP_Add */ + { 0x1000ff75, 18865 }, /* KP_BackTab */ + { 0x0000ff9d, 18876 }, /* KP_Begin */ + { 0x0000ffae, 18885 }, /* KP_Decimal */ + { 0x0000ff9f, 18896 }, /* KP_Delete */ + { 0x0000ffaf, 18906 }, /* KP_Divide */ + { 0x0000ff99, 18916 }, /* KP_Down */ + { 0x0000ff9c, 18924 }, /* KP_End */ + { 0x0000ff8d, 18931 }, /* KP_Enter */ + { 0x0000ffbd, 18940 }, /* KP_Equal */ + { 0x0000ff91, 18949 }, /* KP_F1 */ + { 0x0000ff92, 18955 }, /* KP_F2 */ + { 0x0000ff93, 18961 }, /* KP_F3 */ + { 0x0000ff94, 18967 }, /* KP_F4 */ + { 0x0000ff95, 18973 }, /* KP_Home */ + { 0x0000ff9e, 18981 }, /* KP_Insert */ + { 0x0000ff96, 18991 }, /* KP_Left */ + { 0x0000ffaa, 18999 }, /* KP_Multiply */ + { 0x0000ff9b, 19011 }, /* KP_Next */ + { 0x0000ff9b, 19019 }, /* KP_Page_Down */ + { 0x0000ff9a, 19032 }, /* KP_Page_Up */ + { 0x0000ff9a, 19043 }, /* KP_Prior */ + { 0x0000ff98, 19052 }, /* KP_Right */ + { 0x0000ffac, 19061 }, /* KP_Separator */ + { 0x0000ff80, 19074 }, /* KP_Space */ + { 0x0000ffad, 19083 }, /* KP_Subtract */ + { 0x0000ff89, 19095 }, /* KP_Tab */ + { 0x0000ff97, 19102 }, /* KP_Up */ + { 0x000003a2, 19108 }, /* kra */ + { 0x0000004c, 19112 }, /* L */ + { 0x0000006c, 19114 }, /* l */ + { 0x0000ffc8, 19116 }, /* L1 */ + { 0x0000ffd1, 19119 }, /* L10 */ + { 0x0000ffc9, 19123 }, /* L2 */ + { 0x0000ffca, 19126 }, /* L3 */ + { 0x0000ffcb, 19129 }, /* L4 */ + { 0x0000ffcc, 19132 }, /* L5 */ + { 0x0000ffcd, 19135 }, /* L6 */ + { 0x0000ffce, 19138 }, /* L7 */ + { 0x0000ffcf, 19141 }, /* L8 */ + { 0x0000ffd0, 19144 }, /* L9 */ + { 0x000001c5, 19147 }, /* Lacute */ + { 0x000001e5, 19154 }, /* lacute */ + { 0x0000fed4, 19161 }, /* Last_Virtual_Screen */ + { 0x00000ad9, 19181 }, /* latincross */ + { 0x01001e36, 19192 }, /* Lbelowdot */ + { 0x01001e37, 19202 }, /* lbelowdot */ + { 0x000001a5, 19212 }, /* Lcaron */ + { 0x000001b5, 19219 }, /* lcaron */ + { 0x000003a6, 19226 }, /* Lcedilla */ + { 0x000003b6, 19235 }, /* lcedilla */ + { 0x0000ff51, 19244 }, /* Left */ + { 0x00000abc, 19249 }, /* leftanglebracket */ + { 0x000008fb, 19266 }, /* leftarrow */ + { 0x00000ba3, 19276 }, /* leftcaret */ + { 0x00000ad2, 19286 }, /* leftdoublequotemark */ + { 0x000008af, 19306 }, /* leftmiddlecurlybrace */ + { 0x00000acc, 19327 }, /* leftopentriangle */ + { 0x00000aea, 19344 }, /* leftpointer */ + { 0x000008a1, 19356 }, /* leftradical */ + { 0x00000bda, 19368 }, /* leftshoe */ + { 0x00000ad0, 19377 }, /* leftsinglequotemark */ + { 0x000009f4, 19397 }, /* leftt */ + { 0x00000bdc, 19403 }, /* lefttack */ + { 0x0000003c, 19412 }, /* less */ + { 0x000008bc, 19417 }, /* lessthanequal */ + { 0x000009e5, 19431 }, /* lf */ + { 0x0000ff0a, 19434 }, /* Linefeed */ + { 0x100000af, 19443 }, /* lira */ + { 0x010020a4, 19448 }, /* LiraSign */ + { 0x000008de, 19457 }, /* logicaland */ + { 0x000008df, 19468 }, /* logicalor */ + { 0x100000f6, 19478 }, /* longminus */ + { 0x000009ed, 19488 }, /* lowleftcorner */ + { 0x000009ea, 19502 }, /* lowrightcorner */ + { 0x000001a3, 19517 }, /* Lstroke */ + { 0x000001b3, 19525 }, /* lstroke */ + { 0x0000004d, 19533 }, /* M */ + { 0x0000006d, 19535 }, /* m */ + { 0x01001e40, 19537 }, /* Mabovedot */ + { 0x01001e41, 19547 }, /* mabovedot */ + { 0x000006a5, 19557 }, /* Macedonia_dse */ + { 0x000006b5, 19571 }, /* Macedonia_DSE */ + { 0x000006a2, 19585 }, /* Macedonia_gje */ + { 0x000006b2, 19599 }, /* Macedonia_GJE */ + { 0x000006ac, 19613 }, /* Macedonia_kje */ + { 0x000006bc, 19627 }, /* Macedonia_KJE */ + { 0x000000af, 19641 }, /* macron */ + { 0x0000ff3e, 19648 }, /* Mae_Koho */ + { 0x00000af7, 19657 }, /* malesymbol */ + { 0x00000af0, 19668 }, /* maltesecross */ + { 0x00000abf, 19681 }, /* marker */ + { 0x000000ba, 19688 }, /* masculine */ + { 0x0000ff2c, 19698 }, /* Massyo */ + { 0x0000ff67, 19705 }, /* Menu */ + { 0x0000ffe7, 19710 }, /* Meta_L */ + { 0x0000ffe8, 19717 }, /* Meta_R */ + { 0x010020a5, 19724 }, /* MillSign */ + { 0x0000002d, 19733 }, /* minus */ + { 0x00000ad6, 19739 }, /* minutes */ + { 0x0000ff7e, 19747 }, /* Mode_switch */ + { 0x0000fe77, 19759 }, /* MouseKeys_Accel_Enable */ + { 0x0000fe76, 19782 }, /* MouseKeys_Enable */ + { 0x000000b5, 19799 }, /* mu */ + { 0x0000ff22, 19802 }, /* Muhenkan */ + { 0x0000ff20, 19811 }, /* Multi_key */ + { 0x0000ff3d, 19821 }, /* MultipleCandidate */ + { 0x000000d7, 19839 }, /* multiply */ + { 0x00000af6, 19848 }, /* musicalflat */ + { 0x00000af5, 19860 }, /* musicalsharp */ + { 0x100000a8, 19873 }, /* mute_acute */ + { 0x100000aa, 19884 }, /* mute_asciicircum */ + { 0x100000ac, 19901 }, /* mute_asciitilde */ + { 0x100000ab, 19917 }, /* mute_diaeresis */ + { 0x100000a9, 19932 }, /* mute_grave */ + { 0x0000004e, 19943 }, /* N */ + { 0x0000006e, 19945 }, /* n */ + { 0x000008c5, 19947 }, /* nabla */ + { 0x000001d1, 19953 }, /* Nacute */ + { 0x000001f1, 19960 }, /* nacute */ + { 0x010020a6, 19967 }, /* NairaSign */ + { 0x000001d2, 19977 }, /* Ncaron */ + { 0x000001f2, 19984 }, /* ncaron */ + { 0x000003d1, 19991 }, /* Ncedilla */ + { 0x000003f1, 20000 }, /* ncedilla */ + { 0x010020aa, 20009 }, /* NewSheqelSign */ + { 0x0000ff56, 20023 }, /* Next */ + { 0x0000fed2, 20028 }, /* Next_Virtual_Screen */ + { 0x01002089, 20048 }, /* ninesubscript */ + { 0x01002079, 20062 }, /* ninesuperior */ + { 0x000009e8, 20075 }, /* nl */ + { 0x000000a0, 20078 }, /* nobreakspace */ + { 0x00000000, 20091 }, /* NoSymbol */ + { 0x01002247, 20100 }, /* notapproxeq */ + { 0x01002209, 20112 }, /* notelementof */ + { 0x000008bd, 20125 }, /* notequal */ + { 0x01002262, 20134 }, /* notidentical */ + { 0x000000ac, 20147 }, /* notsign */ + { 0x000000d1, 20155 }, /* Ntilde */ + { 0x000000f1, 20162 }, /* ntilde */ + { 0x0000ff7f, 20169 }, /* Num_Lock */ + { 0x00000023, 20178 }, /* numbersign */ + { 0x000006b0, 20189 }, /* numerosign */ + { 0x0000004f, 20200 }, /* O */ + { 0x0000006f, 20202 }, /* o */ + { 0x000000d3, 20204 }, /* Oacute */ + { 0x000000f3, 20211 }, /* oacute */ + { 0x0100019f, 20218 }, /* Obarred */ + { 0x01000275, 20226 }, /* obarred */ + { 0x01001ecc, 20234 }, /* Obelowdot */ + { 0x01001ecd, 20244 }, /* obelowdot */ + { 0x010001d1, 20254 }, /* Ocaron */ + { 0x010001d2, 20261 }, /* ocaron */ + { 0x000000d4, 20268 }, /* Ocircumflex */ + { 0x000000f4, 20280 }, /* ocircumflex */ + { 0x01001ed0, 20292 }, /* Ocircumflexacute */ + { 0x01001ed1, 20309 }, /* ocircumflexacute */ + { 0x01001ed8, 20326 }, /* Ocircumflexbelowdot */ + { 0x01001ed9, 20346 }, /* ocircumflexbelowdot */ + { 0x01001ed2, 20366 }, /* Ocircumflexgrave */ + { 0x01001ed3, 20383 }, /* ocircumflexgrave */ + { 0x01001ed4, 20400 }, /* Ocircumflexhook */ + { 0x01001ed5, 20416 }, /* ocircumflexhook */ + { 0x01001ed6, 20432 }, /* Ocircumflextilde */ + { 0x01001ed7, 20449 }, /* ocircumflextilde */ + { 0x000000d6, 20466 }, /* Odiaeresis */ + { 0x000000f6, 20477 }, /* odiaeresis */ + { 0x000001d5, 20488 }, /* Odoubleacute */ + { 0x000001f5, 20501 }, /* odoubleacute */ + { 0x000013bc, 20514 }, /* OE */ + { 0x000013bd, 20517 }, /* oe */ + { 0x000001b2, 20520 }, /* ogonek */ + { 0x000000d2, 20527 }, /* Ograve */ + { 0x000000f2, 20534 }, /* ograve */ + { 0x01001ece, 20541 }, /* Ohook */ + { 0x01001ecf, 20547 }, /* ohook */ + { 0x010001a0, 20553 }, /* Ohorn */ + { 0x010001a1, 20559 }, /* ohorn */ + { 0x01001eda, 20565 }, /* Ohornacute */ + { 0x01001edb, 20576 }, /* ohornacute */ + { 0x01001ee2, 20587 }, /* Ohornbelowdot */ + { 0x01001ee3, 20601 }, /* ohornbelowdot */ + { 0x01001edc, 20615 }, /* Ohorngrave */ + { 0x01001edd, 20626 }, /* ohorngrave */ + { 0x01001ede, 20637 }, /* Ohornhook */ + { 0x01001edf, 20647 }, /* ohornhook */ + { 0x01001ee0, 20657 }, /* Ohorntilde */ + { 0x01001ee1, 20668 }, /* ohorntilde */ + { 0x000003d2, 20679 }, /* Omacron */ + { 0x000003f2, 20687 }, /* omacron */ + { 0x00000ac3, 20695 }, /* oneeighth */ + { 0x00000ab2, 20705 }, /* onefifth */ + { 0x000000bd, 20714 }, /* onehalf */ + { 0x000000bc, 20722 }, /* onequarter */ + { 0x00000ab6, 20733 }, /* onesixth */ + { 0x01002081, 20742 }, /* onesubscript */ + { 0x000000b9, 20755 }, /* onesuperior */ + { 0x00000ab0, 20767 }, /* onethird */ + { 0x000000d8, 20776 }, /* Ooblique */ + { 0x000000f8, 20785 }, /* ooblique */ + { 0x00000ae2, 20794 }, /* openrectbullet */ + { 0x00000ae5, 20809 }, /* openstar */ + { 0x00000ae4, 20818 }, /* opentribulletdown */ + { 0x00000ae3, 20836 }, /* opentribulletup */ + { 0x000000aa, 20852 }, /* ordfeminine */ + { 0x1004ff44, 20864 }, /* osfActivate */ + { 0x1004ff31, 20876 }, /* osfAddMode */ + { 0x1004ff08, 20887 }, /* osfBackSpace */ + { 0x1004ff07, 20900 }, /* osfBackTab */ + { 0x1004ff5a, 20911 }, /* osfBeginData */ + { 0x1004ff58, 20924 }, /* osfBeginLine */ + { 0x1004ff69, 20937 }, /* osfCancel */ + { 0x1004ff0b, 20947 }, /* osfClear */ + { 0x1004ff02, 20956 }, /* osfCopy */ + { 0x1004ff03, 20964 }, /* osfCut */ + { 0x1004ffff, 20971 }, /* osfDelete */ + { 0x1004ff72, 20981 }, /* osfDeselectAll */ + { 0x1004ff54, 20996 }, /* osfDown */ + { 0x1004ff59, 21004 }, /* osfEndData */ + { 0x1004ff57, 21015 }, /* osfEndLine */ + { 0x1004ff1b, 21026 }, /* osfEscape */ + { 0x1004ff74, 21036 }, /* osfExtend */ + { 0x1004ff6a, 21046 }, /* osfHelp */ + { 0x1004ff63, 21054 }, /* osfInsert */ + { 0x1004ff51, 21064 }, /* osfLeft */ + { 0x1004ff67, 21072 }, /* osfMenu */ + { 0x1004ff45, 21080 }, /* osfMenuBar */ + { 0x1004ff5e, 21091 }, /* osfNextField */ + { 0x1004ff5c, 21104 }, /* osfNextMenu */ + { 0x1004ff42, 21116 }, /* osfPageDown */ + { 0x1004ff40, 21128 }, /* osfPageLeft */ + { 0x1004ff43, 21140 }, /* osfPageRight */ + { 0x1004ff41, 21153 }, /* osfPageUp */ + { 0x1004ff04, 21163 }, /* osfPaste */ + { 0x1004ff5d, 21172 }, /* osfPrevField */ + { 0x1004ff5b, 21185 }, /* osfPrevMenu */ + { 0x1004ff32, 21197 }, /* osfPrimaryPaste */ + { 0x1004ff33, 21213 }, /* osfQuickPaste */ + { 0x1004ff73, 21227 }, /* osfReselect */ + { 0x1004ff78, 21239 }, /* osfRestore */ + { 0x1004ff53, 21250 }, /* osfRight */ + { 0x1004ff60, 21259 }, /* osfSelect */ + { 0x1004ff71, 21269 }, /* osfSelectAll */ + { 0x1004ff65, 21282 }, /* osfUndo */ + { 0x1004ff52, 21290 }, /* osfUp */ + { 0x000000d8, 21296 }, /* Oslash */ + { 0x000000f8, 21303 }, /* oslash */ + { 0x000000d5, 21310 }, /* Otilde */ + { 0x000000f5, 21317 }, /* otilde */ + { 0x00000bc0, 21324 }, /* overbar */ + { 0x0000fe78, 21332 }, /* Overlay1_Enable */ + { 0x0000fe79, 21348 }, /* Overlay2_Enable */ + { 0x0000047e, 21364 }, /* overline */ + { 0x00000050, 21373 }, /* P */ + { 0x00000070, 21375 }, /* p */ + { 0x01001e56, 21377 }, /* Pabovedot */ + { 0x01001e57, 21387 }, /* pabovedot */ + { 0x0000ff56, 21397 }, /* Page_Down */ + { 0x0000ff55, 21407 }, /* Page_Up */ + { 0x000000b6, 21415 }, /* paragraph */ + { 0x00000028, 21425 }, /* parenleft */ + { 0x00000029, 21435 }, /* parenright */ + { 0x01002202, 21446 }, /* partdifferential */ + { 0x000008ef, 21463 }, /* partialderivative */ + { 0x0000ff13, 21481 }, /* Pause */ + { 0x00000025, 21487 }, /* percent */ + { 0x0000002e, 21495 }, /* period */ + { 0x000000b7, 21502 }, /* periodcentered */ + { 0x00000ad5, 21517 }, /* permille */ + { 0x010020a7, 21526 }, /* PesetaSign */ + { 0x00000afb, 21537 }, /* phonographcopyright */ + { 0x0000002b, 21557 }, /* plus */ + { 0x000000b1, 21562 }, /* plusminus */ + { 0x0000fefa, 21572 }, /* Pointer_Accelerate */ + { 0x0000fee9, 21591 }, /* Pointer_Button1 */ + { 0x0000feea, 21607 }, /* Pointer_Button2 */ + { 0x0000feeb, 21623 }, /* Pointer_Button3 */ + { 0x0000feec, 21639 }, /* Pointer_Button4 */ + { 0x0000feed, 21655 }, /* Pointer_Button5 */ + { 0x0000fee8, 21671 }, /* Pointer_Button_Dflt */ + { 0x0000feef, 21691 }, /* Pointer_DblClick1 */ + { 0x0000fef0, 21709 }, /* Pointer_DblClick2 */ + { 0x0000fef1, 21727 }, /* Pointer_DblClick3 */ + { 0x0000fef2, 21745 }, /* Pointer_DblClick4 */ + { 0x0000fef3, 21763 }, /* Pointer_DblClick5 */ + { 0x0000feee, 21781 }, /* Pointer_DblClick_Dflt */ + { 0x0000fefb, 21803 }, /* Pointer_DfltBtnNext */ + { 0x0000fefc, 21823 }, /* Pointer_DfltBtnPrev */ + { 0x0000fee3, 21843 }, /* Pointer_Down */ + { 0x0000fee6, 21856 }, /* Pointer_DownLeft */ + { 0x0000fee7, 21873 }, /* Pointer_DownRight */ + { 0x0000fef5, 21891 }, /* Pointer_Drag1 */ + { 0x0000fef6, 21905 }, /* Pointer_Drag2 */ + { 0x0000fef7, 21919 }, /* Pointer_Drag3 */ + { 0x0000fef8, 21933 }, /* Pointer_Drag4 */ + { 0x0000fefd, 21947 }, /* Pointer_Drag5 */ + { 0x0000fef4, 21961 }, /* Pointer_Drag_Dflt */ + { 0x0000fef9, 21979 }, /* Pointer_EnableKeys */ + { 0x0000fee0, 21998 }, /* Pointer_Left */ + { 0x0000fee1, 22011 }, /* Pointer_Right */ + { 0x0000fee2, 22025 }, /* Pointer_Up */ + { 0x0000fee4, 22036 }, /* Pointer_UpLeft */ + { 0x0000fee5, 22051 }, /* Pointer_UpRight */ + { 0x00000ad4, 22067 }, /* prescription */ + { 0x0000fed1, 22080 }, /* Prev_Virtual_Screen */ + { 0x0000ff3e, 22100 }, /* PreviousCandidate */ + { 0x0000ff61, 22118 }, /* Print */ + { 0x0000ff55, 22124 }, /* Prior */ + { 0x000004b0, 22130 }, /* prolongedsound */ + { 0x00000aa6, 22145 }, /* punctspace */ + { 0x00000051, 22156 }, /* Q */ + { 0x00000071, 22158 }, /* q */ + { 0x00000bcc, 22160 }, /* quad */ + { 0x0000003f, 22165 }, /* question */ + { 0x000000bf, 22174 }, /* questiondown */ + { 0x00000022, 22187 }, /* quotedbl */ + { 0x00000060, 22196 }, /* quoteleft */ + { 0x00000027, 22206 }, /* quoteright */ + { 0x00000052, 22217 }, /* R */ + { 0x00000072, 22219 }, /* r */ + { 0x0000ffd2, 22221 }, /* R1 */ + { 0x0000ffdb, 22224 }, /* R10 */ + { 0x0000ffdc, 22228 }, /* R11 */ + { 0x0000ffdd, 22232 }, /* R12 */ + { 0x0000ffde, 22236 }, /* R13 */ + { 0x0000ffdf, 22240 }, /* R14 */ + { 0x0000ffe0, 22244 }, /* R15 */ + { 0x0000ffd3, 22248 }, /* R2 */ + { 0x0000ffd4, 22251 }, /* R3 */ + { 0x0000ffd5, 22254 }, /* R4 */ + { 0x0000ffd6, 22257 }, /* R5 */ + { 0x0000ffd7, 22260 }, /* R6 */ + { 0x0000ffd8, 22263 }, /* R7 */ + { 0x0000ffd9, 22266 }, /* R8 */ + { 0x0000ffda, 22269 }, /* R9 */ + { 0x000001c0, 22272 }, /* Racute */ + { 0x000001e0, 22279 }, /* racute */ + { 0x000008d6, 22286 }, /* radical */ + { 0x000001d8, 22294 }, /* Rcaron */ + { 0x000001f8, 22301 }, /* rcaron */ + { 0x000003a3, 22308 }, /* Rcedilla */ + { 0x000003b3, 22317 }, /* rcedilla */ + { 0x0000ff66, 22326 }, /* Redo */ + { 0x000000ae, 22331 }, /* registered */ + { 0x0000fe72, 22342 }, /* RepeatKeys_Enable */ + { 0x1000ff6c, 22360 }, /* Reset */ + { 0x0000ff0d, 22366 }, /* Return */ + { 0x0000ff53, 22373 }, /* Right */ + { 0x00000abe, 22379 }, /* rightanglebracket */ + { 0x000008fd, 22397 }, /* rightarrow */ + { 0x00000ba6, 22408 }, /* rightcaret */ + { 0x00000ad3, 22419 }, /* rightdoublequotemark */ + { 0x000008b0, 22440 }, /* rightmiddlecurlybrace */ + { 0x000008b7, 22462 }, /* rightmiddlesummation */ + { 0x00000acd, 22483 }, /* rightopentriangle */ + { 0x00000aeb, 22501 }, /* rightpointer */ + { 0x00000bd8, 22514 }, /* rightshoe */ + { 0x00000ad1, 22524 }, /* rightsinglequotemark */ + { 0x000009f5, 22545 }, /* rightt */ + { 0x00000bfc, 22552 }, /* righttack */ + { 0x0000ff24, 22562 }, /* Romaji */ + { 0x010020a8, 22569 }, /* RupeeSign */ + { 0x00000053, 22579 }, /* S */ + { 0x00000073, 22581 }, /* s */ + { 0x01001e60, 22583 }, /* Sabovedot */ + { 0x01001e61, 22593 }, /* sabovedot */ + { 0x000001a6, 22603 }, /* Sacute */ + { 0x000001b6, 22610 }, /* sacute */ + { 0x000001a9, 22617 }, /* Scaron */ + { 0x000001b9, 22624 }, /* scaron */ + { 0x000001aa, 22631 }, /* Scedilla */ + { 0x000001ba, 22640 }, /* scedilla */ + { 0x0100018f, 22649 }, /* SCHWA */ + { 0x01000259, 22655 }, /* schwa */ + { 0x000002de, 22661 }, /* Scircumflex */ + { 0x000002fe, 22673 }, /* scircumflex */ + { 0x0000ff7e, 22685 }, /* script_switch */ + { 0x0000ff14, 22699 }, /* Scroll_Lock */ + { 0x00000ad7, 22711 }, /* seconds */ + { 0x000000a7, 22719 }, /* section */ + { 0x0000ff60, 22727 }, /* Select */ + { 0x0000003b, 22734 }, /* semicolon */ + { 0x000004df, 22744 }, /* semivoicedsound */ + { 0x000006a1, 22760 }, /* Serbian_dje */ + { 0x000006b1, 22772 }, /* Serbian_DJE */ + { 0x000006af, 22784 }, /* Serbian_dze */ + { 0x000006bf, 22796 }, /* Serbian_DZE */ + { 0x000006a8, 22808 }, /* Serbian_je */ + { 0x000006b8, 22819 }, /* Serbian_JE */ + { 0x000006a9, 22830 }, /* Serbian_lje */ + { 0x000006b9, 22842 }, /* Serbian_LJE */ + { 0x000006aa, 22854 }, /* Serbian_nje */ + { 0x000006ba, 22866 }, /* Serbian_NJE */ + { 0x000006ab, 22878 }, /* Serbian_tshe */ + { 0x000006bb, 22891 }, /* Serbian_TSHE */ + { 0x00000ac6, 22904 }, /* seveneighths */ + { 0x01002087, 22917 }, /* sevensubscript */ + { 0x01002077, 22932 }, /* sevensuperior */ + { 0x0000ffe1, 22946 }, /* Shift_L */ + { 0x0000ffe6, 22954 }, /* Shift_Lock */ + { 0x0000ffe2, 22965 }, /* Shift_R */ + { 0x00000aca, 22973 }, /* signaturemark */ + { 0x00000aac, 22987 }, /* signifblank */ + { 0x000008c9, 22999 }, /* similarequal */ + { 0x0000ff3c, 23012 }, /* SingleCandidate */ + { 0x00000afd, 23028 }, /* singlelowquotemark */ + { 0x01000d85, 23047 }, /* Sinh_a */ + { 0x01000d86, 23054 }, /* Sinh_aa */ + { 0x01000dcf, 23062 }, /* Sinh_aa2 */ + { 0x01000d87, 23071 }, /* Sinh_ae */ + { 0x01000dd0, 23079 }, /* Sinh_ae2 */ + { 0x01000d88, 23088 }, /* Sinh_aee */ + { 0x01000dd1, 23097 }, /* Sinh_aee2 */ + { 0x01000d93, 23107 }, /* Sinh_ai */ + { 0x01000ddb, 23115 }, /* Sinh_ai2 */ + { 0x01000dca, 23124 }, /* Sinh_al */ + { 0x01000d96, 23132 }, /* Sinh_au */ + { 0x01000dde, 23140 }, /* Sinh_au2 */ + { 0x01000db6, 23149 }, /* Sinh_ba */ + { 0x01000db7, 23157 }, /* Sinh_bha */ + { 0x01000da0, 23166 }, /* Sinh_ca */ + { 0x01000da1, 23174 }, /* Sinh_cha */ + { 0x01000da9, 23183 }, /* Sinh_dda */ + { 0x01000daa, 23192 }, /* Sinh_ddha */ + { 0x01000daf, 23202 }, /* Sinh_dha */ + { 0x01000db0, 23211 }, /* Sinh_dhha */ + { 0x01000d91, 23221 }, /* Sinh_e */ + { 0x01000dd9, 23228 }, /* Sinh_e2 */ + { 0x01000d92, 23236 }, /* Sinh_ee */ + { 0x01000dda, 23244 }, /* Sinh_ee2 */ + { 0x01000dc6, 23253 }, /* Sinh_fa */ + { 0x01000d9c, 23261 }, /* Sinh_ga */ + { 0x01000d9d, 23269 }, /* Sinh_gha */ + { 0x01000d83, 23278 }, /* Sinh_h2 */ + { 0x01000dc4, 23286 }, /* Sinh_ha */ + { 0x01000d89, 23294 }, /* Sinh_i */ + { 0x01000dd2, 23301 }, /* Sinh_i2 */ + { 0x01000d8a, 23309 }, /* Sinh_ii */ + { 0x01000dd3, 23317 }, /* Sinh_ii2 */ + { 0x01000da2, 23326 }, /* Sinh_ja */ + { 0x01000da3, 23334 }, /* Sinh_jha */ + { 0x01000da5, 23343 }, /* Sinh_jnya */ + { 0x01000d9a, 23353 }, /* Sinh_ka */ + { 0x01000d9b, 23361 }, /* Sinh_kha */ + { 0x01000df4, 23370 }, /* Sinh_kunddaliya */ + { 0x01000dbd, 23386 }, /* Sinh_la */ + { 0x01000dc5, 23394 }, /* Sinh_lla */ + { 0x01000d8f, 23403 }, /* Sinh_lu */ + { 0x01000ddf, 23411 }, /* Sinh_lu2 */ + { 0x01000d90, 23420 }, /* Sinh_luu */ + { 0x01000df3, 23429 }, /* Sinh_luu2 */ + { 0x01000db8, 23439 }, /* Sinh_ma */ + { 0x01000db9, 23447 }, /* Sinh_mba */ + { 0x01000db1, 23456 }, /* Sinh_na */ + { 0x01000dac, 23464 }, /* Sinh_ndda */ + { 0x01000db3, 23474 }, /* Sinh_ndha */ + { 0x01000d82, 23484 }, /* Sinh_ng */ + { 0x01000d9e, 23492 }, /* Sinh_ng2 */ + { 0x01000d9f, 23501 }, /* Sinh_nga */ + { 0x01000da6, 23510 }, /* Sinh_nja */ + { 0x01000dab, 23519 }, /* Sinh_nna */ + { 0x01000da4, 23528 }, /* Sinh_nya */ + { 0x01000d94, 23537 }, /* Sinh_o */ + { 0x01000ddc, 23544 }, /* Sinh_o2 */ + { 0x01000d95, 23552 }, /* Sinh_oo */ + { 0x01000ddd, 23560 }, /* Sinh_oo2 */ + { 0x01000db4, 23569 }, /* Sinh_pa */ + { 0x01000db5, 23577 }, /* Sinh_pha */ + { 0x01000dbb, 23586 }, /* Sinh_ra */ + { 0x01000d8d, 23594 }, /* Sinh_ri */ + { 0x01000d8e, 23602 }, /* Sinh_rii */ + { 0x01000dd8, 23611 }, /* Sinh_ru2 */ + { 0x01000df2, 23620 }, /* Sinh_ruu2 */ + { 0x01000dc3, 23630 }, /* Sinh_sa */ + { 0x01000dc1, 23638 }, /* Sinh_sha */ + { 0x01000dc2, 23647 }, /* Sinh_ssha */ + { 0x01000dad, 23657 }, /* Sinh_tha */ + { 0x01000dae, 23666 }, /* Sinh_thha */ + { 0x01000da7, 23676 }, /* Sinh_tta */ + { 0x01000da8, 23685 }, /* Sinh_ttha */ + { 0x01000d8b, 23695 }, /* Sinh_u */ + { 0x01000dd4, 23702 }, /* Sinh_u2 */ + { 0x01000d8c, 23710 }, /* Sinh_uu */ + { 0x01000dd6, 23718 }, /* Sinh_uu2 */ + { 0x01000dc0, 23727 }, /* Sinh_va */ + { 0x01000dba, 23735 }, /* Sinh_ya */ + { 0x01002086, 23743 }, /* sixsubscript */ + { 0x01002076, 23756 }, /* sixsuperior */ + { 0x0000002f, 23768 }, /* slash */ + { 0x0000fe73, 23774 }, /* SlowKeys_Enable */ + { 0x000009e0, 23790 }, /* soliddiamond */ + { 0x00000020, 23803 }, /* space */ + { 0x0100221a, 23809 }, /* squareroot */ + { 0x000000df, 23820 }, /* ssharp */ + { 0x000000a3, 23827 }, /* sterling */ + { 0x0000fe75, 23836 }, /* StickyKeys_Enable */ + { 0x01002263, 23854 }, /* stricteq */ + { 0x0000ff66, 23863 }, /* SunAgain */ + { 0x0000ff7e, 23872 }, /* SunAltGraph */ + { 0x1005ff77, 23884 }, /* SunAudioLowerVolume */ + { 0x1005ff78, 23904 }, /* SunAudioMute */ + { 0x1005ff79, 23917 }, /* SunAudioRaiseVolume */ + { 0x0000ff20, 23937 }, /* SunCompose */ + { 0x1005ff72, 23948 }, /* SunCopy */ + { 0x1005ff75, 23956 }, /* SunCut */ + { 0x1005ff10, 23963 }, /* SunF36 */ + { 0x1005ff11, 23970 }, /* SunF37 */ + { 0x1005ff03, 23977 }, /* SunFA_Acute */ + { 0x1005ff05, 23989 }, /* SunFA_Cedilla */ + { 0x1005ff01, 24003 }, /* SunFA_Circum */ + { 0x1005ff04, 24016 }, /* SunFA_Diaeresis */ + { 0x1005ff00, 24032 }, /* SunFA_Grave */ + { 0x1005ff02, 24044 }, /* SunFA_Tilde */ + { 0x0000ff68, 24056 }, /* SunFind */ + { 0x1005ff71, 24064 }, /* SunFront */ + { 0x1005ff73, 24073 }, /* SunOpen */ + { 0x0000ff56, 24081 }, /* SunPageDown */ + { 0x0000ff55, 24093 }, /* SunPageUp */ + { 0x1005ff74, 24103 }, /* SunPaste */ + { 0x1005ff76, 24112 }, /* SunPowerSwitch */ + { 0x1005ff7d, 24127 }, /* SunPowerSwitchShift */ + { 0x0000ff61, 24147 }, /* SunPrint_Screen */ + { 0x1005ff70, 24163 }, /* SunProps */ + { 0x0000ff69, 24172 }, /* SunStop */ + { 0x1005ff60, 24180 }, /* SunSys_Req */ + { 0x0000ff65, 24191 }, /* SunUndo */ + { 0x1005ff7a, 24199 }, /* SunVideoDegauss */ + { 0x1005ff7b, 24215 }, /* SunVideoLowerBrightness */ + { 0x1005ff7c, 24239 }, /* SunVideoRaiseBrightness */ + { 0x0000ffeb, 24263 }, /* Super_L */ + { 0x0000ffec, 24271 }, /* Super_R */ + { 0x0000ff15, 24279 }, /* Sys_Req */ + { 0x1000ff6d, 24287 }, /* System */ + { 0x00000054, 24294 }, /* T */ + { 0x00000074, 24296 }, /* t */ + { 0x0000ff09, 24298 }, /* Tab */ + { 0x01001e6a, 24302 }, /* Tabovedot */ + { 0x01001e6b, 24312 }, /* tabovedot */ + { 0x000001ab, 24322 }, /* Tcaron */ + { 0x000001bb, 24329 }, /* tcaron */ + { 0x000001de, 24336 }, /* Tcedilla */ + { 0x000001fe, 24345 }, /* tcedilla */ + { 0x00000af9, 24354 }, /* telephone */ + { 0x00000afa, 24364 }, /* telephonerecorder */ + { 0x0000fed5, 24382 }, /* Terminate_Server */ + { 0x00000ddf, 24399 }, /* Thai_baht */ + { 0x00000dba, 24409 }, /* Thai_bobaimai */ + { 0x00000da8, 24423 }, /* Thai_chochan */ + { 0x00000daa, 24436 }, /* Thai_chochang */ + { 0x00000da9, 24450 }, /* Thai_choching */ + { 0x00000dac, 24464 }, /* Thai_chochoe */ + { 0x00000dae, 24477 }, /* Thai_dochada */ + { 0x00000db4, 24490 }, /* Thai_dodek */ + { 0x00000dbd, 24501 }, /* Thai_fofa */ + { 0x00000dbf, 24511 }, /* Thai_fofan */ + { 0x00000dcb, 24522 }, /* Thai_hohip */ + { 0x00000dce, 24533 }, /* Thai_honokhuk */ + { 0x00000da2, 24547 }, /* Thai_khokhai */ + { 0x00000da5, 24560 }, /* Thai_khokhon */ + { 0x00000da3, 24573 }, /* Thai_khokhuat */ + { 0x00000da4, 24587 }, /* Thai_khokhwai */ + { 0x00000da6, 24601 }, /* Thai_khorakhang */ + { 0x00000da1, 24617 }, /* Thai_kokai */ + { 0x00000de5, 24628 }, /* Thai_lakkhangyao */ + { 0x00000df7, 24645 }, /* Thai_lekchet */ + { 0x00000df5, 24658 }, /* Thai_lekha */ + { 0x00000df6, 24669 }, /* Thai_lekhok */ + { 0x00000df9, 24681 }, /* Thai_lekkao */ + { 0x00000df1, 24693 }, /* Thai_leknung */ + { 0x00000df8, 24706 }, /* Thai_lekpaet */ + { 0x00000df3, 24719 }, /* Thai_leksam */ + { 0x00000df4, 24731 }, /* Thai_leksi */ + { 0x00000df2, 24742 }, /* Thai_leksong */ + { 0x00000df0, 24755 }, /* Thai_leksun */ + { 0x00000dcc, 24767 }, /* Thai_lochula */ + { 0x00000dc5, 24780 }, /* Thai_loling */ + { 0x00000dc6, 24792 }, /* Thai_lu */ + { 0x00000deb, 24800 }, /* Thai_maichattawa */ + { 0x00000de8, 24817 }, /* Thai_maiek */ + { 0x00000dd1, 24828 }, /* Thai_maihanakat */ + { 0x00000dde, 24844 }, /* Thai_maihanakat_maitho */ + { 0x00000de7, 24867 }, /* Thai_maitaikhu */ + { 0x00000de9, 24882 }, /* Thai_maitho */ + { 0x00000dea, 24894 }, /* Thai_maitri */ + { 0x00000de6, 24906 }, /* Thai_maiyamok */ + { 0x00000dc1, 24920 }, /* Thai_moma */ + { 0x00000da7, 24930 }, /* Thai_ngongu */ + { 0x00000ded, 24942 }, /* Thai_nikhahit */ + { 0x00000db3, 24956 }, /* Thai_nonen */ + { 0x00000db9, 24967 }, /* Thai_nonu */ + { 0x00000dcd, 24977 }, /* Thai_oang */ + { 0x00000dcf, 24987 }, /* Thai_paiyannoi */ + { 0x00000dda, 25002 }, /* Thai_phinthu */ + { 0x00000dbe, 25015 }, /* Thai_phophan */ + { 0x00000dbc, 25028 }, /* Thai_phophung */ + { 0x00000dc0, 25042 }, /* Thai_phosamphao */ + { 0x00000dbb, 25058 }, /* Thai_popla */ + { 0x00000dc3, 25069 }, /* Thai_rorua */ + { 0x00000dc4, 25080 }, /* Thai_ru */ + { 0x00000dd0, 25088 }, /* Thai_saraa */ + { 0x00000dd2, 25099 }, /* Thai_saraaa */ + { 0x00000de1, 25111 }, /* Thai_saraae */ + { 0x00000de4, 25123 }, /* Thai_saraaimaimalai */ + { 0x00000de3, 25143 }, /* Thai_saraaimaimuan */ + { 0x00000dd3, 25162 }, /* Thai_saraam */ + { 0x00000de0, 25174 }, /* Thai_sarae */ + { 0x00000dd4, 25185 }, /* Thai_sarai */ + { 0x00000dd5, 25196 }, /* Thai_saraii */ + { 0x00000de2, 25208 }, /* Thai_sarao */ + { 0x00000dd8, 25219 }, /* Thai_sarau */ + { 0x00000dd6, 25230 }, /* Thai_saraue */ + { 0x00000dd7, 25242 }, /* Thai_sarauee */ + { 0x00000dd9, 25255 }, /* Thai_sarauu */ + { 0x00000dc9, 25267 }, /* Thai_sorusi */ + { 0x00000dc8, 25279 }, /* Thai_sosala */ + { 0x00000dab, 25291 }, /* Thai_soso */ + { 0x00000dca, 25301 }, /* Thai_sosua */ + { 0x00000dec, 25312 }, /* Thai_thanthakhat */ + { 0x00000db1, 25329 }, /* Thai_thonangmontho */ + { 0x00000db2, 25348 }, /* Thai_thophuthao */ + { 0x00000db7, 25364 }, /* Thai_thothahan */ + { 0x00000db0, 25379 }, /* Thai_thothan */ + { 0x00000db8, 25392 }, /* Thai_thothong */ + { 0x00000db6, 25406 }, /* Thai_thothung */ + { 0x00000daf, 25420 }, /* Thai_topatak */ + { 0x00000db5, 25433 }, /* Thai_totao */ + { 0x00000dc7, 25444 }, /* Thai_wowaen */ + { 0x00000dc2, 25456 }, /* Thai_yoyak */ + { 0x00000dad, 25467 }, /* Thai_yoying */ + { 0x000008c0, 25479 }, /* therefore */ + { 0x00000aa7, 25489 }, /* thinspace */ + { 0x000000de, 25499 }, /* THORN */ + { 0x000000de, 25505 }, /* Thorn */ + { 0x000000fe, 25511 }, /* thorn */ + { 0x00000ac4, 25517 }, /* threeeighths */ + { 0x00000ab4, 25530 }, /* threefifths */ + { 0x000000be, 25542 }, /* threequarters */ + { 0x01002083, 25556 }, /* threesubscript */ + { 0x000000b3, 25571 }, /* threesuperior */ + { 0x0100222d, 25585 }, /* tintegral */ + { 0x000008a4, 25595 }, /* topintegral */ + { 0x000008ab, 25607 }, /* topleftparens */ + { 0x000008a2, 25621 }, /* topleftradical */ + { 0x000008a7, 25636 }, /* topleftsqbracket */ + { 0x000008b1, 25653 }, /* topleftsummation */ + { 0x000008ad, 25670 }, /* toprightparens */ + { 0x000008a9, 25685 }, /* toprightsqbracket */ + { 0x000008b5, 25703 }, /* toprightsummation */ + { 0x000009f7, 25721 }, /* topt */ + { 0x000008b3, 25726 }, /* topvertsummationconnector */ + { 0x0000ff2b, 25752 }, /* Touroku */ + { 0x00000ac9, 25760 }, /* trademark */ + { 0x00000acb, 25770 }, /* trademarkincircle */ + { 0x000003ac, 25788 }, /* Tslash */ + { 0x000003bc, 25795 }, /* tslash */ + { 0x00000ab3, 25802 }, /* twofifths */ + { 0x01002082, 25812 }, /* twosubscript */ + { 0x000000b2, 25825 }, /* twosuperior */ + { 0x00000ab1, 25837 }, /* twothirds */ + { 0x00000055, 25847 }, /* U */ + { 0x00000075, 25849 }, /* u */ + { 0x000000da, 25851 }, /* Uacute */ + { 0x000000fa, 25858 }, /* uacute */ + { 0x01001ee4, 25865 }, /* Ubelowdot */ + { 0x01001ee5, 25875 }, /* ubelowdot */ + { 0x000002dd, 25885 }, /* Ubreve */ + { 0x000002fd, 25892 }, /* ubreve */ + { 0x000000db, 25899 }, /* Ucircumflex */ + { 0x000000fb, 25911 }, /* ucircumflex */ + { 0x000000dc, 25923 }, /* Udiaeresis */ + { 0x000000fc, 25934 }, /* udiaeresis */ + { 0x000001db, 25945 }, /* Udoubleacute */ + { 0x000001fb, 25958 }, /* udoubleacute */ + { 0x000000d9, 25971 }, /* Ugrave */ + { 0x000000f9, 25978 }, /* ugrave */ + { 0x01001ee6, 25985 }, /* Uhook */ + { 0x01001ee7, 25991 }, /* uhook */ + { 0x010001af, 25997 }, /* Uhorn */ + { 0x010001b0, 26003 }, /* uhorn */ + { 0x01001ee8, 26009 }, /* Uhornacute */ + { 0x01001ee9, 26020 }, /* uhornacute */ + { 0x01001ef0, 26031 }, /* Uhornbelowdot */ + { 0x01001ef1, 26045 }, /* uhornbelowdot */ + { 0x01001eea, 26059 }, /* Uhorngrave */ + { 0x01001eeb, 26070 }, /* uhorngrave */ + { 0x01001eec, 26081 }, /* Uhornhook */ + { 0x01001eed, 26091 }, /* uhornhook */ + { 0x01001eee, 26101 }, /* Uhorntilde */ + { 0x01001eef, 26112 }, /* uhorntilde */ + { 0x000006ad, 26123 }, /* Ukrainian_ghe_with_upturn */ + { 0x000006bd, 26149 }, /* Ukrainian_GHE_WITH_UPTURN */ + { 0x000006a6, 26175 }, /* Ukrainian_i */ + { 0x000006b6, 26187 }, /* Ukrainian_I */ + { 0x000006a4, 26199 }, /* Ukrainian_ie */ + { 0x000006b4, 26212 }, /* Ukrainian_IE */ + { 0x000006a7, 26225 }, /* Ukrainian_yi */ + { 0x000006b7, 26238 }, /* Ukrainian_YI */ + { 0x000006a6, 26251 }, /* Ukranian_i */ + { 0x000006b6, 26262 }, /* Ukranian_I */ + { 0x000006a4, 26273 }, /* Ukranian_je */ + { 0x000006b4, 26285 }, /* Ukranian_JE */ + { 0x000006a7, 26297 }, /* Ukranian_yi */ + { 0x000006b7, 26309 }, /* Ukranian_YI */ + { 0x000003de, 26321 }, /* Umacron */ + { 0x000003fe, 26329 }, /* umacron */ + { 0x00000bc6, 26337 }, /* underbar */ + { 0x0000005f, 26346 }, /* underscore */ + { 0x0000ff65, 26357 }, /* Undo */ + { 0x000008dd, 26362 }, /* union */ + { 0x000003d9, 26368 }, /* Uogonek */ + { 0x000003f9, 26376 }, /* uogonek */ + { 0x0000ff52, 26384 }, /* Up */ + { 0x000008fc, 26387 }, /* uparrow */ + { 0x00000ba9, 26395 }, /* upcaret */ + { 0x000009ec, 26403 }, /* upleftcorner */ + { 0x000009eb, 26416 }, /* uprightcorner */ + { 0x00000bc3, 26430 }, /* upshoe */ + { 0x00000bd3, 26437 }, /* upstile */ + { 0x00000bce, 26445 }, /* uptack */ + { 0x000001d9, 26452 }, /* Uring */ + { 0x000001f9, 26458 }, /* uring */ + { 0x1000ff6e, 26464 }, /* User */ + { 0x000003dd, 26469 }, /* Utilde */ + { 0x000003fd, 26476 }, /* utilde */ + { 0x00000056, 26483 }, /* V */ + { 0x00000076, 26485 }, /* v */ + { 0x000008c1, 26487 }, /* variation */ + { 0x000009f8, 26497 }, /* vertbar */ + { 0x000008a6, 26505 }, /* vertconnector */ + { 0x000004de, 26519 }, /* voicedsound */ + { 0x00ffffff, 26531 }, /* VoidSymbol */ + { 0x000009e9, 26542 }, /* vt */ + { 0x00000057, 26545 }, /* W */ + { 0x00000077, 26547 }, /* w */ + { 0x01001e82, 26549 }, /* Wacute */ + { 0x01001e83, 26556 }, /* wacute */ + { 0x01000174, 26563 }, /* Wcircumflex */ + { 0x01000175, 26575 }, /* wcircumflex */ + { 0x01001e84, 26587 }, /* Wdiaeresis */ + { 0x01001e85, 26598 }, /* wdiaeresis */ + { 0x01001e80, 26609 }, /* Wgrave */ + { 0x01001e81, 26616 }, /* wgrave */ + { 0x010020a9, 26623 }, /* WonSign */ + { 0x00000058, 26631 }, /* X */ + { 0x00000078, 26633 }, /* x */ + { 0x01001e8a, 26635 }, /* Xabovedot */ + { 0x01001e8b, 26645 }, /* xabovedot */ + { 0x1008ff39, 26655 }, /* XF86AddFavorite */ + { 0x1008ff50, 26671 }, /* XF86ApplicationLeft */ + { 0x1008ff51, 26691 }, /* XF86ApplicationRight */ + { 0x1008ff9b, 26712 }, /* XF86AudioCycleTrack */ + { 0x1008ff97, 26732 }, /* XF86AudioForward */ + { 0x1008ff11, 26749 }, /* XF86AudioLowerVolume */ + { 0x1008ff32, 26770 }, /* XF86AudioMedia */ + { 0x1008ffb2, 26785 }, /* XF86AudioMicMute */ + { 0x1008ff12, 26802 }, /* XF86AudioMute */ + { 0x1008ff17, 26816 }, /* XF86AudioNext */ + { 0x1008ff31, 26830 }, /* XF86AudioPause */ + { 0x1008ff14, 26845 }, /* XF86AudioPlay */ + { 0x1008ff16, 26859 }, /* XF86AudioPrev */ + { 0x1008ff13, 26873 }, /* XF86AudioRaiseVolume */ + { 0x1008ff99, 26894 }, /* XF86AudioRandomPlay */ + { 0x1008ff1c, 26914 }, /* XF86AudioRecord */ + { 0x1008ff98, 26930 }, /* XF86AudioRepeat */ + { 0x1008ff3e, 26946 }, /* XF86AudioRewind */ + { 0x1008ff15, 26962 }, /* XF86AudioStop */ + { 0x1008ff8d, 26976 }, /* XF86Away */ + { 0x1008ff26, 26985 }, /* XF86Back */ + { 0x1008ff3f, 26994 }, /* XF86BackForward */ + { 0x1008ff93, 27010 }, /* XF86Battery */ + { 0x1008ffa6, 27022 }, /* XF86Blue */ + { 0x1008ff94, 27031 }, /* XF86Bluetooth */ + { 0x1008ff52, 27045 }, /* XF86Book */ + { 0x1008ff3b, 27054 }, /* XF86BrightnessAdjust */ + { 0x1008ff54, 27075 }, /* XF86Calculater */ + { 0x1008ff1d, 27090 }, /* XF86Calculator */ + { 0x1008ff20, 27105 }, /* XF86Calendar */ + { 0x1008ff53, 27118 }, /* XF86CD */ + { 0x1008ff55, 27125 }, /* XF86Clear */ + { 0x1008fe21, 27135 }, /* XF86ClearGrab */ + { 0x1008ff56, 27149 }, /* XF86Close */ + { 0x1008ff3d, 27159 }, /* XF86Community */ + { 0x1008ff22, 27173 }, /* XF86ContrastAdjust */ + { 0x1008ff57, 27192 }, /* XF86Copy */ + { 0x1008ff58, 27201 }, /* XF86Cut */ + { 0x1008ff9c, 27209 }, /* XF86CycleAngle */ + { 0x1008ff59, 27224 }, /* XF86Display */ + { 0x1008ff5b, 27236 }, /* XF86Documents */ + { 0x1008ff5a, 27250 }, /* XF86DOS */ + { 0x1008ff2c, 27258 }, /* XF86Eject */ + { 0x1008ff5c, 27268 }, /* XF86Excel */ + { 0x1008ff5d, 27278 }, /* XF86Explorer */ + { 0x1008ff30, 27291 }, /* XF86Favorites */ + { 0x1008ff3c, 27305 }, /* XF86Finance */ + { 0x1008ff27, 27317 }, /* XF86Forward */ + { 0x1008ff9d, 27329 }, /* XF86FrameBack */ + { 0x1008ff9e, 27343 }, /* XF86FrameForward */ + { 0x1008ff5e, 27360 }, /* XF86Game */ + { 0x1008ff5f, 27369 }, /* XF86Go */ + { 0x1008ffa4, 27376 }, /* XF86Green */ + { 0x1008ffa8, 27386 }, /* XF86Hibernate */ + { 0x1008ff37, 27400 }, /* XF86History */ + { 0x1008ff18, 27412 }, /* XF86HomePage */ + { 0x1008ff3a, 27425 }, /* XF86HotLinks */ + { 0x1008ff60, 27438 }, /* XF86iTouch */ + { 0x1008ff06, 27449 }, /* XF86KbdBrightnessDown */ + { 0x1008ff05, 27471 }, /* XF86KbdBrightnessUp */ + { 0x1008ff04, 27491 }, /* XF86KbdLightOnOff */ + { 0x1008ff40, 27509 }, /* XF86Launch0 */ + { 0x1008ff41, 27521 }, /* XF86Launch1 */ + { 0x1008ff42, 27533 }, /* XF86Launch2 */ + { 0x1008ff43, 27545 }, /* XF86Launch3 */ + { 0x1008ff44, 27557 }, /* XF86Launch4 */ + { 0x1008ff45, 27569 }, /* XF86Launch5 */ + { 0x1008ff46, 27581 }, /* XF86Launch6 */ + { 0x1008ff47, 27593 }, /* XF86Launch7 */ + { 0x1008ff48, 27605 }, /* XF86Launch8 */ + { 0x1008ff49, 27617 }, /* XF86Launch9 */ + { 0x1008ff4a, 27629 }, /* XF86LaunchA */ + { 0x1008ff4b, 27641 }, /* XF86LaunchB */ + { 0x1008ff4c, 27653 }, /* XF86LaunchC */ + { 0x1008ff4d, 27665 }, /* XF86LaunchD */ + { 0x1008ff4e, 27677 }, /* XF86LaunchE */ + { 0x1008ff4f, 27689 }, /* XF86LaunchF */ + { 0x1008ff35, 27701 }, /* XF86LightBulb */ + { 0x1008fe25, 27715 }, /* XF86LogGrabInfo */ + { 0x1008ff61, 27731 }, /* XF86LogOff */ + { 0x1008fe24, 27742 }, /* XF86LogWindowTree */ + { 0x1008ff19, 27760 }, /* XF86Mail */ + { 0x1008ff90, 27769 }, /* XF86MailForward */ + { 0x1008ff62, 27785 }, /* XF86Market */ + { 0x1008ff63, 27796 }, /* XF86Meeting */ + { 0x1008ff1e, 27808 }, /* XF86Memo */ + { 0x1008ff65, 27817 }, /* XF86MenuKB */ + { 0x1008ff66, 27828 }, /* XF86MenuPB */ + { 0x1008ff8e, 27839 }, /* XF86Messenger */ + { 0x1008ff01, 27853 }, /* XF86ModeLock */ + { 0x1008ff03, 27866 }, /* XF86MonBrightnessDown */ + { 0x1008ff02, 27888 }, /* XF86MonBrightnessUp */ + { 0x1008ff92, 27908 }, /* XF86Music */ + { 0x1008ff33, 27918 }, /* XF86MyComputer */ + { 0x1008ff67, 27933 }, /* XF86MySites */ + { 0x1008ff68, 27945 }, /* XF86New */ + { 0x1008ff69, 27953 }, /* XF86News */ + { 0x1008fe22, 27962 }, /* XF86Next_VMode */ + { 0x1008ff6a, 27977 }, /* XF86OfficeHome */ + { 0x1008ff6b, 27992 }, /* XF86Open */ + { 0x1008ff38, 28001 }, /* XF86OpenURL */ + { 0x1008ff6c, 28013 }, /* XF86Option */ + { 0x1008ff6d, 28024 }, /* XF86Paste */ + { 0x1008ff6e, 28034 }, /* XF86Phone */ + { 0x1008ff91, 28044 }, /* XF86Pictures */ + { 0x1008ff21, 28057 }, /* XF86PowerDown */ + { 0x1008ff2a, 28071 }, /* XF86PowerOff */ + { 0x1008fe23, 28084 }, /* XF86Prev_VMode */ + { 0x1008ff70, 28099 }, /* XF86Q */ + { 0x1008ffa3, 28105 }, /* XF86Red */ + { 0x1008ff29, 28113 }, /* XF86Refresh */ + { 0x1008ff73, 28125 }, /* XF86Reload */ + { 0x1008ff72, 28136 }, /* XF86Reply */ + { 0x1008ff24, 28146 }, /* XF86RockerDown */ + { 0x1008ff25, 28161 }, /* XF86RockerEnter */ + { 0x1008ff23, 28177 }, /* XF86RockerUp */ + { 0x1008ff74, 28190 }, /* XF86RotateWindows */ + { 0x1008ff76, 28208 }, /* XF86RotationKB */ + { 0x1008ff75, 28223 }, /* XF86RotationPB */ + { 0x1008ff77, 28238 }, /* XF86Save */ + { 0x1008ff2d, 28247 }, /* XF86ScreenSaver */ + { 0x1008ff7a, 28263 }, /* XF86ScrollClick */ + { 0x1008ff79, 28279 }, /* XF86ScrollDown */ + { 0x1008ff78, 28294 }, /* XF86ScrollUp */ + { 0x1008ff1b, 28307 }, /* XF86Search */ + { 0x1008ffa0, 28318 }, /* XF86Select */ + { 0x1008ff7b, 28329 }, /* XF86Send */ + { 0x1008ff36, 28338 }, /* XF86Shop */ + { 0x1008ff2f, 28347 }, /* XF86Sleep */ + { 0x1008ff7c, 28357 }, /* XF86Spell */ + { 0x1008ff7d, 28367 }, /* XF86SplitScreen */ + { 0x1008ff10, 28383 }, /* XF86Standby */ + { 0x1008ff1a, 28395 }, /* XF86Start */ + { 0x1008ff28, 28405 }, /* XF86Stop */ + { 0x1008ff9a, 28414 }, /* XF86Subtitle */ + { 0x1008ff7e, 28427 }, /* XF86Support */ + { 0x1008ffa7, 28439 }, /* XF86Suspend */ + { 0x1008fe01, 28451 }, /* XF86Switch_VT_1 */ + { 0x1008fe0a, 28467 }, /* XF86Switch_VT_10 */ + { 0x1008fe0b, 28484 }, /* XF86Switch_VT_11 */ + { 0x1008fe0c, 28501 }, /* XF86Switch_VT_12 */ + { 0x1008fe02, 28518 }, /* XF86Switch_VT_2 */ + { 0x1008fe03, 28534 }, /* XF86Switch_VT_3 */ + { 0x1008fe04, 28550 }, /* XF86Switch_VT_4 */ + { 0x1008fe05, 28566 }, /* XF86Switch_VT_5 */ + { 0x1008fe06, 28582 }, /* XF86Switch_VT_6 */ + { 0x1008fe07, 28598 }, /* XF86Switch_VT_7 */ + { 0x1008fe08, 28614 }, /* XF86Switch_VT_8 */ + { 0x1008fe09, 28630 }, /* XF86Switch_VT_9 */ + { 0x1008ff7f, 28646 }, /* XF86TaskPane */ + { 0x1008ff80, 28659 }, /* XF86Terminal */ + { 0x1008ff9f, 28672 }, /* XF86Time */ + { 0x1008ff1f, 28681 }, /* XF86ToDoList */ + { 0x1008ff81, 28694 }, /* XF86Tools */ + { 0x1008ffa2, 28704 }, /* XF86TopMenu */ + { 0x1008ffb1, 28716 }, /* XF86TouchpadOff */ + { 0x1008ffb0, 28732 }, /* XF86TouchpadOn */ + { 0x1008ffa9, 28747 }, /* XF86TouchpadToggle */ + { 0x1008ff82, 28766 }, /* XF86Travel */ + { 0x1008fe20, 28777 }, /* XF86Ungrab */ + { 0x1008ff85, 28788 }, /* XF86User1KB */ + { 0x1008ff86, 28800 }, /* XF86User2KB */ + { 0x1008ff84, 28812 }, /* XF86UserPB */ + { 0x1008ff96, 28823 }, /* XF86UWB */ + { 0x1008ff34, 28831 }, /* XF86VendorHome */ + { 0x1008ff87, 28846 }, /* XF86Video */ + { 0x1008ffa1, 28856 }, /* XF86View */ + { 0x1008ff2b, 28865 }, /* XF86WakeUp */ + { 0x1008ff8f, 28876 }, /* XF86WebCam */ + { 0x1008ff88, 28887 }, /* XF86WheelButton */ + { 0x1008ff95, 28903 }, /* XF86WLAN */ + { 0x1008ff89, 28912 }, /* XF86Word */ + { 0x1008ff2e, 28921 }, /* XF86WWW */ + { 0x1008ff8a, 28929 }, /* XF86Xfer */ + { 0x1008ffa5, 28938 }, /* XF86Yellow */ + { 0x1008ff8b, 28949 }, /* XF86ZoomIn */ + { 0x1008ff8c, 28960 }, /* XF86ZoomOut */ + { 0x00000059, 28972 }, /* Y */ + { 0x00000079, 28974 }, /* y */ + { 0x000000dd, 28976 }, /* Yacute */ + { 0x000000fd, 28983 }, /* yacute */ + { 0x01001ef4, 28990 }, /* Ybelowdot */ + { 0x01001ef5, 29000 }, /* ybelowdot */ + { 0x01000176, 29010 }, /* Ycircumflex */ + { 0x01000177, 29022 }, /* ycircumflex */ + { 0x000000ff, 29034 }, /* ydiaeresis */ + { 0x000013be, 29045 }, /* Ydiaeresis */ + { 0x000000a5, 29056 }, /* yen */ + { 0x01001ef2, 29060 }, /* Ygrave */ + { 0x01001ef3, 29067 }, /* ygrave */ + { 0x01001ef6, 29074 }, /* Yhook */ + { 0x01001ef7, 29080 }, /* yhook */ + { 0x01001ef8, 29086 }, /* Ytilde */ + { 0x01001ef9, 29093 }, /* ytilde */ + { 0x0000005a, 29100 }, /* Z */ + { 0x0000007a, 29102 }, /* z */ + { 0x000001af, 29104 }, /* Zabovedot */ + { 0x000001bf, 29114 }, /* zabovedot */ + { 0x000001ac, 29124 }, /* Zacute */ + { 0x000001bc, 29131 }, /* zacute */ + { 0x000001ae, 29138 }, /* Zcaron */ + { 0x000001be, 29145 }, /* zcaron */ + { 0x0000ff3d, 29152 }, /* Zen_Koho */ + { 0x0000ff28, 29161 }, /* Zenkaku */ + { 0x0000ff2a, 29169 }, /* Zenkaku_Hankaku */ + { 0x01002080, 29185 }, /* zerosubscript */ + { 0x01002070, 29199 }, /* zerosuperior */ + { 0x010001b5, 29212 }, /* Zstroke */ + { 0x010001b6, 29220 }, /* zstroke */ }; static const struct name_keysym keysym_to_name[] = { - { "NoSymbol", XKB_KEY_NoSymbol }, - { "space", XKB_KEY_space }, - { "exclam", XKB_KEY_exclam }, - { "quotedbl", XKB_KEY_quotedbl }, - { "numbersign", XKB_KEY_numbersign }, - { "dollar", XKB_KEY_dollar }, - { "percent", XKB_KEY_percent }, - { "ampersand", XKB_KEY_ampersand }, - { "apostrophe", XKB_KEY_apostrophe }, - { "parenleft", XKB_KEY_parenleft }, - { "parenright", XKB_KEY_parenright }, - { "asterisk", XKB_KEY_asterisk }, - { "plus", XKB_KEY_plus }, - { "comma", XKB_KEY_comma }, - { "minus", XKB_KEY_minus }, - { "period", XKB_KEY_period }, - { "slash", XKB_KEY_slash }, - { "0", XKB_KEY_0 }, - { "1", XKB_KEY_1 }, - { "2", XKB_KEY_2 }, - { "3", XKB_KEY_3 }, - { "4", XKB_KEY_4 }, - { "5", XKB_KEY_5 }, - { "6", XKB_KEY_6 }, - { "7", XKB_KEY_7 }, - { "8", XKB_KEY_8 }, - { "9", XKB_KEY_9 }, - { "colon", XKB_KEY_colon }, - { "semicolon", XKB_KEY_semicolon }, - { "less", XKB_KEY_less }, - { "equal", XKB_KEY_equal }, - { "greater", XKB_KEY_greater }, - { "question", XKB_KEY_question }, - { "at", XKB_KEY_at }, - { "A", XKB_KEY_A }, - { "B", XKB_KEY_B }, - { "C", XKB_KEY_C }, - { "D", XKB_KEY_D }, - { "E", XKB_KEY_E }, - { "F", XKB_KEY_F }, - { "G", XKB_KEY_G }, - { "H", XKB_KEY_H }, - { "I", XKB_KEY_I }, - { "J", XKB_KEY_J }, - { "K", XKB_KEY_K }, - { "L", XKB_KEY_L }, - { "M", XKB_KEY_M }, - { "N", XKB_KEY_N }, - { "O", XKB_KEY_O }, - { "P", XKB_KEY_P }, - { "Q", XKB_KEY_Q }, - { "R", XKB_KEY_R }, - { "S", XKB_KEY_S }, - { "T", XKB_KEY_T }, - { "U", XKB_KEY_U }, - { "V", XKB_KEY_V }, - { "W", XKB_KEY_W }, - { "X", XKB_KEY_X }, - { "Y", XKB_KEY_Y }, - { "Z", XKB_KEY_Z }, - { "bracketleft", XKB_KEY_bracketleft }, - { "backslash", XKB_KEY_backslash }, - { "bracketright", XKB_KEY_bracketright }, - { "asciicircum", XKB_KEY_asciicircum }, - { "underscore", XKB_KEY_underscore }, - { "grave", XKB_KEY_grave }, - { "a", XKB_KEY_a }, - { "b", XKB_KEY_b }, - { "c", XKB_KEY_c }, - { "d", XKB_KEY_d }, - { "e", XKB_KEY_e }, - { "f", XKB_KEY_f }, - { "g", XKB_KEY_g }, - { "h", XKB_KEY_h }, - { "i", XKB_KEY_i }, - { "j", XKB_KEY_j }, - { "k", XKB_KEY_k }, - { "l", XKB_KEY_l }, - { "m", XKB_KEY_m }, - { "n", XKB_KEY_n }, - { "o", XKB_KEY_o }, - { "p", XKB_KEY_p }, - { "q", XKB_KEY_q }, - { "r", XKB_KEY_r }, - { "s", XKB_KEY_s }, - { "t", XKB_KEY_t }, - { "u", XKB_KEY_u }, - { "v", XKB_KEY_v }, - { "w", XKB_KEY_w }, - { "x", XKB_KEY_x }, - { "y", XKB_KEY_y }, - { "z", XKB_KEY_z }, - { "braceleft", XKB_KEY_braceleft }, - { "bar", XKB_KEY_bar }, - { "braceright", XKB_KEY_braceright }, - { "asciitilde", XKB_KEY_asciitilde }, - { "nobreakspace", XKB_KEY_nobreakspace }, - { "exclamdown", XKB_KEY_exclamdown }, - { "cent", XKB_KEY_cent }, - { "sterling", XKB_KEY_sterling }, - { "currency", XKB_KEY_currency }, - { "yen", XKB_KEY_yen }, - { "brokenbar", XKB_KEY_brokenbar }, - { "section", XKB_KEY_section }, - { "diaeresis", XKB_KEY_diaeresis }, - { "copyright", XKB_KEY_copyright }, - { "ordfeminine", XKB_KEY_ordfeminine }, - { "guillemotleft", XKB_KEY_guillemotleft }, - { "notsign", XKB_KEY_notsign }, - { "hyphen", XKB_KEY_hyphen }, - { "registered", XKB_KEY_registered }, - { "macron", XKB_KEY_macron }, - { "degree", XKB_KEY_degree }, - { "plusminus", XKB_KEY_plusminus }, - { "twosuperior", XKB_KEY_twosuperior }, - { "threesuperior", XKB_KEY_threesuperior }, - { "acute", XKB_KEY_acute }, - { "mu", XKB_KEY_mu }, - { "paragraph", XKB_KEY_paragraph }, - { "periodcentered", XKB_KEY_periodcentered }, - { "cedilla", XKB_KEY_cedilla }, - { "onesuperior", XKB_KEY_onesuperior }, - { "masculine", XKB_KEY_masculine }, - { "guillemotright", XKB_KEY_guillemotright }, - { "onequarter", XKB_KEY_onequarter }, - { "onehalf", XKB_KEY_onehalf }, - { "threequarters", XKB_KEY_threequarters }, - { "questiondown", XKB_KEY_questiondown }, - { "Agrave", XKB_KEY_Agrave }, - { "Aacute", XKB_KEY_Aacute }, - { "Acircumflex", XKB_KEY_Acircumflex }, - { "Atilde", XKB_KEY_Atilde }, - { "Adiaeresis", XKB_KEY_Adiaeresis }, - { "Aring", XKB_KEY_Aring }, - { "AE", XKB_KEY_AE }, - { "Ccedilla", XKB_KEY_Ccedilla }, - { "Egrave", XKB_KEY_Egrave }, - { "Eacute", XKB_KEY_Eacute }, - { "Ecircumflex", XKB_KEY_Ecircumflex }, - { "Ediaeresis", XKB_KEY_Ediaeresis }, - { "Igrave", XKB_KEY_Igrave }, - { "Iacute", XKB_KEY_Iacute }, - { "Icircumflex", XKB_KEY_Icircumflex }, - { "Idiaeresis", XKB_KEY_Idiaeresis }, - { "ETH", XKB_KEY_ETH }, - { "Ntilde", XKB_KEY_Ntilde }, - { "Ograve", XKB_KEY_Ograve }, - { "Oacute", XKB_KEY_Oacute }, - { "Ocircumflex", XKB_KEY_Ocircumflex }, - { "Otilde", XKB_KEY_Otilde }, - { "Odiaeresis", XKB_KEY_Odiaeresis }, - { "multiply", XKB_KEY_multiply }, - { "Oslash", XKB_KEY_Oslash }, - { "Ugrave", XKB_KEY_Ugrave }, - { "Uacute", XKB_KEY_Uacute }, - { "Ucircumflex", XKB_KEY_Ucircumflex }, - { "Udiaeresis", XKB_KEY_Udiaeresis }, - { "Yacute", XKB_KEY_Yacute }, - { "THORN", XKB_KEY_THORN }, - { "ssharp", XKB_KEY_ssharp }, - { "agrave", XKB_KEY_agrave }, - { "aacute", XKB_KEY_aacute }, - { "acircumflex", XKB_KEY_acircumflex }, - { "atilde", XKB_KEY_atilde }, - { "adiaeresis", XKB_KEY_adiaeresis }, - { "aring", XKB_KEY_aring }, - { "ae", XKB_KEY_ae }, - { "ccedilla", XKB_KEY_ccedilla }, - { "egrave", XKB_KEY_egrave }, - { "eacute", XKB_KEY_eacute }, - { "ecircumflex", XKB_KEY_ecircumflex }, - { "ediaeresis", XKB_KEY_ediaeresis }, - { "igrave", XKB_KEY_igrave }, - { "iacute", XKB_KEY_iacute }, - { "icircumflex", XKB_KEY_icircumflex }, - { "idiaeresis", XKB_KEY_idiaeresis }, - { "eth", XKB_KEY_eth }, - { "ntilde", XKB_KEY_ntilde }, - { "ograve", XKB_KEY_ograve }, - { "oacute", XKB_KEY_oacute }, - { "ocircumflex", XKB_KEY_ocircumflex }, - { "otilde", XKB_KEY_otilde }, - { "odiaeresis", XKB_KEY_odiaeresis }, - { "division", XKB_KEY_division }, - { "oslash", XKB_KEY_oslash }, - { "ugrave", XKB_KEY_ugrave }, - { "uacute", XKB_KEY_uacute }, - { "ucircumflex", XKB_KEY_ucircumflex }, - { "udiaeresis", XKB_KEY_udiaeresis }, - { "yacute", XKB_KEY_yacute }, - { "thorn", XKB_KEY_thorn }, - { "ydiaeresis", XKB_KEY_ydiaeresis }, - { "Aogonek", XKB_KEY_Aogonek }, - { "breve", XKB_KEY_breve }, - { "Lstroke", XKB_KEY_Lstroke }, - { "Lcaron", XKB_KEY_Lcaron }, - { "Sacute", XKB_KEY_Sacute }, - { "Scaron", XKB_KEY_Scaron }, - { "Scedilla", XKB_KEY_Scedilla }, - { "Tcaron", XKB_KEY_Tcaron }, - { "Zacute", XKB_KEY_Zacute }, - { "Zcaron", XKB_KEY_Zcaron }, - { "Zabovedot", XKB_KEY_Zabovedot }, - { "aogonek", XKB_KEY_aogonek }, - { "ogonek", XKB_KEY_ogonek }, - { "lstroke", XKB_KEY_lstroke }, - { "lcaron", XKB_KEY_lcaron }, - { "sacute", XKB_KEY_sacute }, - { "caron", XKB_KEY_caron }, - { "scaron", XKB_KEY_scaron }, - { "scedilla", XKB_KEY_scedilla }, - { "tcaron", XKB_KEY_tcaron }, - { "zacute", XKB_KEY_zacute }, - { "doubleacute", XKB_KEY_doubleacute }, - { "zcaron", XKB_KEY_zcaron }, - { "zabovedot", XKB_KEY_zabovedot }, - { "Racute", XKB_KEY_Racute }, - { "Abreve", XKB_KEY_Abreve }, - { "Lacute", XKB_KEY_Lacute }, - { "Cacute", XKB_KEY_Cacute }, - { "Ccaron", XKB_KEY_Ccaron }, - { "Eogonek", XKB_KEY_Eogonek }, - { "Ecaron", XKB_KEY_Ecaron }, - { "Dcaron", XKB_KEY_Dcaron }, - { "Dstroke", XKB_KEY_Dstroke }, - { "Nacute", XKB_KEY_Nacute }, - { "Ncaron", XKB_KEY_Ncaron }, - { "Odoubleacute", XKB_KEY_Odoubleacute }, - { "Rcaron", XKB_KEY_Rcaron }, - { "Uring", XKB_KEY_Uring }, - { "Udoubleacute", XKB_KEY_Udoubleacute }, - { "Tcedilla", XKB_KEY_Tcedilla }, - { "racute", XKB_KEY_racute }, - { "abreve", XKB_KEY_abreve }, - { "lacute", XKB_KEY_lacute }, - { "cacute", XKB_KEY_cacute }, - { "ccaron", XKB_KEY_ccaron }, - { "eogonek", XKB_KEY_eogonek }, - { "ecaron", XKB_KEY_ecaron }, - { "dcaron", XKB_KEY_dcaron }, - { "dstroke", XKB_KEY_dstroke }, - { "nacute", XKB_KEY_nacute }, - { "ncaron", XKB_KEY_ncaron }, - { "odoubleacute", XKB_KEY_odoubleacute }, - { "rcaron", XKB_KEY_rcaron }, - { "uring", XKB_KEY_uring }, - { "udoubleacute", XKB_KEY_udoubleacute }, - { "tcedilla", XKB_KEY_tcedilla }, - { "abovedot", XKB_KEY_abovedot }, - { "Hstroke", XKB_KEY_Hstroke }, - { "Hcircumflex", XKB_KEY_Hcircumflex }, - { "Iabovedot", XKB_KEY_Iabovedot }, - { "Gbreve", XKB_KEY_Gbreve }, - { "Jcircumflex", XKB_KEY_Jcircumflex }, - { "hstroke", XKB_KEY_hstroke }, - { "hcircumflex", XKB_KEY_hcircumflex }, - { "idotless", XKB_KEY_idotless }, - { "gbreve", XKB_KEY_gbreve }, - { "jcircumflex", XKB_KEY_jcircumflex }, - { "Cabovedot", XKB_KEY_Cabovedot }, - { "Ccircumflex", XKB_KEY_Ccircumflex }, - { "Gabovedot", XKB_KEY_Gabovedot }, - { "Gcircumflex", XKB_KEY_Gcircumflex }, - { "Ubreve", XKB_KEY_Ubreve }, - { "Scircumflex", XKB_KEY_Scircumflex }, - { "cabovedot", XKB_KEY_cabovedot }, - { "ccircumflex", XKB_KEY_ccircumflex }, - { "gabovedot", XKB_KEY_gabovedot }, - { "gcircumflex", XKB_KEY_gcircumflex }, - { "ubreve", XKB_KEY_ubreve }, - { "scircumflex", XKB_KEY_scircumflex }, - { "kra", XKB_KEY_kra }, - { "Rcedilla", XKB_KEY_Rcedilla }, - { "Itilde", XKB_KEY_Itilde }, - { "Lcedilla", XKB_KEY_Lcedilla }, - { "Emacron", XKB_KEY_Emacron }, - { "Gcedilla", XKB_KEY_Gcedilla }, - { "Tslash", XKB_KEY_Tslash }, - { "rcedilla", XKB_KEY_rcedilla }, - { "itilde", XKB_KEY_itilde }, - { "lcedilla", XKB_KEY_lcedilla }, - { "emacron", XKB_KEY_emacron }, - { "gcedilla", XKB_KEY_gcedilla }, - { "tslash", XKB_KEY_tslash }, - { "ENG", XKB_KEY_ENG }, - { "eng", XKB_KEY_eng }, - { "Amacron", XKB_KEY_Amacron }, - { "Iogonek", XKB_KEY_Iogonek }, - { "Eabovedot", XKB_KEY_Eabovedot }, - { "Imacron", XKB_KEY_Imacron }, - { "Ncedilla", XKB_KEY_Ncedilla }, - { "Omacron", XKB_KEY_Omacron }, - { "Kcedilla", XKB_KEY_Kcedilla }, - { "Uogonek", XKB_KEY_Uogonek }, - { "Utilde", XKB_KEY_Utilde }, - { "Umacron", XKB_KEY_Umacron }, - { "amacron", XKB_KEY_amacron }, - { "iogonek", XKB_KEY_iogonek }, - { "eabovedot", XKB_KEY_eabovedot }, - { "imacron", XKB_KEY_imacron }, - { "ncedilla", XKB_KEY_ncedilla }, - { "omacron", XKB_KEY_omacron }, - { "kcedilla", XKB_KEY_kcedilla }, - { "uogonek", XKB_KEY_uogonek }, - { "utilde", XKB_KEY_utilde }, - { "umacron", XKB_KEY_umacron }, - { "overline", XKB_KEY_overline }, - { "kana_fullstop", XKB_KEY_kana_fullstop }, - { "kana_openingbracket", XKB_KEY_kana_openingbracket }, - { "kana_closingbracket", XKB_KEY_kana_closingbracket }, - { "kana_comma", XKB_KEY_kana_comma }, - { "kana_conjunctive", XKB_KEY_kana_conjunctive }, - { "kana_WO", XKB_KEY_kana_WO }, - { "kana_a", XKB_KEY_kana_a }, - { "kana_i", XKB_KEY_kana_i }, - { "kana_u", XKB_KEY_kana_u }, - { "kana_e", XKB_KEY_kana_e }, - { "kana_o", XKB_KEY_kana_o }, - { "kana_ya", XKB_KEY_kana_ya }, - { "kana_yu", XKB_KEY_kana_yu }, - { "kana_yo", XKB_KEY_kana_yo }, - { "kana_tsu", XKB_KEY_kana_tsu }, - { "prolongedsound", XKB_KEY_prolongedsound }, - { "kana_A", XKB_KEY_kana_A }, - { "kana_I", XKB_KEY_kana_I }, - { "kana_U", XKB_KEY_kana_U }, - { "kana_E", XKB_KEY_kana_E }, - { "kana_O", XKB_KEY_kana_O }, - { "kana_KA", XKB_KEY_kana_KA }, - { "kana_KI", XKB_KEY_kana_KI }, - { "kana_KU", XKB_KEY_kana_KU }, - { "kana_KE", XKB_KEY_kana_KE }, - { "kana_KO", XKB_KEY_kana_KO }, - { "kana_SA", XKB_KEY_kana_SA }, - { "kana_SHI", XKB_KEY_kana_SHI }, - { "kana_SU", XKB_KEY_kana_SU }, - { "kana_SE", XKB_KEY_kana_SE }, - { "kana_SO", XKB_KEY_kana_SO }, - { "kana_TA", XKB_KEY_kana_TA }, - { "kana_CHI", XKB_KEY_kana_CHI }, - { "kana_TSU", XKB_KEY_kana_TSU }, - { "kana_TE", XKB_KEY_kana_TE }, - { "kana_TO", XKB_KEY_kana_TO }, - { "kana_NA", XKB_KEY_kana_NA }, - { "kana_NI", XKB_KEY_kana_NI }, - { "kana_NU", XKB_KEY_kana_NU }, - { "kana_NE", XKB_KEY_kana_NE }, - { "kana_NO", XKB_KEY_kana_NO }, - { "kana_HA", XKB_KEY_kana_HA }, - { "kana_HI", XKB_KEY_kana_HI }, - { "kana_FU", XKB_KEY_kana_FU }, - { "kana_HE", XKB_KEY_kana_HE }, - { "kana_HO", XKB_KEY_kana_HO }, - { "kana_MA", XKB_KEY_kana_MA }, - { "kana_MI", XKB_KEY_kana_MI }, - { "kana_MU", XKB_KEY_kana_MU }, - { "kana_ME", XKB_KEY_kana_ME }, - { "kana_MO", XKB_KEY_kana_MO }, - { "kana_YA", XKB_KEY_kana_YA }, - { "kana_YU", XKB_KEY_kana_YU }, - { "kana_YO", XKB_KEY_kana_YO }, - { "kana_RA", XKB_KEY_kana_RA }, - { "kana_RI", XKB_KEY_kana_RI }, - { "kana_RU", XKB_KEY_kana_RU }, - { "kana_RE", XKB_KEY_kana_RE }, - { "kana_RO", XKB_KEY_kana_RO }, - { "kana_WA", XKB_KEY_kana_WA }, - { "kana_N", XKB_KEY_kana_N }, - { "voicedsound", XKB_KEY_voicedsound }, - { "semivoicedsound", XKB_KEY_semivoicedsound }, - { "Arabic_comma", XKB_KEY_Arabic_comma }, - { "Arabic_semicolon", XKB_KEY_Arabic_semicolon }, - { "Arabic_question_mark", XKB_KEY_Arabic_question_mark }, - { "Arabic_hamza", XKB_KEY_Arabic_hamza }, - { "Arabic_maddaonalef", XKB_KEY_Arabic_maddaonalef }, - { "Arabic_hamzaonalef", XKB_KEY_Arabic_hamzaonalef }, - { "Arabic_hamzaonwaw", XKB_KEY_Arabic_hamzaonwaw }, - { "Arabic_hamzaunderalef", XKB_KEY_Arabic_hamzaunderalef }, - { "Arabic_hamzaonyeh", XKB_KEY_Arabic_hamzaonyeh }, - { "Arabic_alef", XKB_KEY_Arabic_alef }, - { "Arabic_beh", XKB_KEY_Arabic_beh }, - { "Arabic_tehmarbuta", XKB_KEY_Arabic_tehmarbuta }, - { "Arabic_teh", XKB_KEY_Arabic_teh }, - { "Arabic_theh", XKB_KEY_Arabic_theh }, - { "Arabic_jeem", XKB_KEY_Arabic_jeem }, - { "Arabic_hah", XKB_KEY_Arabic_hah }, - { "Arabic_khah", XKB_KEY_Arabic_khah }, - { "Arabic_dal", XKB_KEY_Arabic_dal }, - { "Arabic_thal", XKB_KEY_Arabic_thal }, - { "Arabic_ra", XKB_KEY_Arabic_ra }, - { "Arabic_zain", XKB_KEY_Arabic_zain }, - { "Arabic_seen", XKB_KEY_Arabic_seen }, - { "Arabic_sheen", XKB_KEY_Arabic_sheen }, - { "Arabic_sad", XKB_KEY_Arabic_sad }, - { "Arabic_dad", XKB_KEY_Arabic_dad }, - { "Arabic_tah", XKB_KEY_Arabic_tah }, - { "Arabic_zah", XKB_KEY_Arabic_zah }, - { "Arabic_ain", XKB_KEY_Arabic_ain }, - { "Arabic_ghain", XKB_KEY_Arabic_ghain }, - { "Arabic_tatweel", XKB_KEY_Arabic_tatweel }, - { "Arabic_feh", XKB_KEY_Arabic_feh }, - { "Arabic_qaf", XKB_KEY_Arabic_qaf }, - { "Arabic_kaf", XKB_KEY_Arabic_kaf }, - { "Arabic_lam", XKB_KEY_Arabic_lam }, - { "Arabic_meem", XKB_KEY_Arabic_meem }, - { "Arabic_noon", XKB_KEY_Arabic_noon }, - { "Arabic_ha", XKB_KEY_Arabic_ha }, - { "Arabic_waw", XKB_KEY_Arabic_waw }, - { "Arabic_alefmaksura", XKB_KEY_Arabic_alefmaksura }, - { "Arabic_yeh", XKB_KEY_Arabic_yeh }, - { "Arabic_fathatan", XKB_KEY_Arabic_fathatan }, - { "Arabic_dammatan", XKB_KEY_Arabic_dammatan }, - { "Arabic_kasratan", XKB_KEY_Arabic_kasratan }, - { "Arabic_fatha", XKB_KEY_Arabic_fatha }, - { "Arabic_damma", XKB_KEY_Arabic_damma }, - { "Arabic_kasra", XKB_KEY_Arabic_kasra }, - { "Arabic_shadda", XKB_KEY_Arabic_shadda }, - { "Arabic_sukun", XKB_KEY_Arabic_sukun }, - { "Serbian_dje", XKB_KEY_Serbian_dje }, - { "Macedonia_gje", XKB_KEY_Macedonia_gje }, - { "Cyrillic_io", XKB_KEY_Cyrillic_io }, - { "Ukrainian_ie", XKB_KEY_Ukrainian_ie }, - { "Macedonia_dse", XKB_KEY_Macedonia_dse }, - { "Ukrainian_i", XKB_KEY_Ukrainian_i }, - { "Ukrainian_yi", XKB_KEY_Ukrainian_yi }, - { "Cyrillic_je", XKB_KEY_Cyrillic_je }, - { "Cyrillic_lje", XKB_KEY_Cyrillic_lje }, - { "Cyrillic_nje", XKB_KEY_Cyrillic_nje }, - { "Serbian_tshe", XKB_KEY_Serbian_tshe }, - { "Macedonia_kje", XKB_KEY_Macedonia_kje }, - { "Ukrainian_ghe_with_upturn", XKB_KEY_Ukrainian_ghe_with_upturn }, - { "Byelorussian_shortu", XKB_KEY_Byelorussian_shortu }, - { "Cyrillic_dzhe", XKB_KEY_Cyrillic_dzhe }, - { "numerosign", XKB_KEY_numerosign }, - { "Serbian_DJE", XKB_KEY_Serbian_DJE }, - { "Macedonia_GJE", XKB_KEY_Macedonia_GJE }, - { "Cyrillic_IO", XKB_KEY_Cyrillic_IO }, - { "Ukrainian_IE", XKB_KEY_Ukrainian_IE }, - { "Macedonia_DSE", XKB_KEY_Macedonia_DSE }, - { "Ukrainian_I", XKB_KEY_Ukrainian_I }, - { "Ukrainian_YI", XKB_KEY_Ukrainian_YI }, - { "Cyrillic_JE", XKB_KEY_Cyrillic_JE }, - { "Cyrillic_LJE", XKB_KEY_Cyrillic_LJE }, - { "Cyrillic_NJE", XKB_KEY_Cyrillic_NJE }, - { "Serbian_TSHE", XKB_KEY_Serbian_TSHE }, - { "Macedonia_KJE", XKB_KEY_Macedonia_KJE }, - { "Ukrainian_GHE_WITH_UPTURN", XKB_KEY_Ukrainian_GHE_WITH_UPTURN }, - { "Byelorussian_SHORTU", XKB_KEY_Byelorussian_SHORTU }, - { "Cyrillic_DZHE", XKB_KEY_Cyrillic_DZHE }, - { "Cyrillic_yu", XKB_KEY_Cyrillic_yu }, - { "Cyrillic_a", XKB_KEY_Cyrillic_a }, - { "Cyrillic_be", XKB_KEY_Cyrillic_be }, - { "Cyrillic_tse", XKB_KEY_Cyrillic_tse }, - { "Cyrillic_de", XKB_KEY_Cyrillic_de }, - { "Cyrillic_ie", XKB_KEY_Cyrillic_ie }, - { "Cyrillic_ef", XKB_KEY_Cyrillic_ef }, - { "Cyrillic_ghe", XKB_KEY_Cyrillic_ghe }, - { "Cyrillic_ha", XKB_KEY_Cyrillic_ha }, - { "Cyrillic_i", XKB_KEY_Cyrillic_i }, - { "Cyrillic_shorti", XKB_KEY_Cyrillic_shorti }, - { "Cyrillic_ka", XKB_KEY_Cyrillic_ka }, - { "Cyrillic_el", XKB_KEY_Cyrillic_el }, - { "Cyrillic_em", XKB_KEY_Cyrillic_em }, - { "Cyrillic_en", XKB_KEY_Cyrillic_en }, - { "Cyrillic_o", XKB_KEY_Cyrillic_o }, - { "Cyrillic_pe", XKB_KEY_Cyrillic_pe }, - { "Cyrillic_ya", XKB_KEY_Cyrillic_ya }, - { "Cyrillic_er", XKB_KEY_Cyrillic_er }, - { "Cyrillic_es", XKB_KEY_Cyrillic_es }, - { "Cyrillic_te", XKB_KEY_Cyrillic_te }, - { "Cyrillic_u", XKB_KEY_Cyrillic_u }, - { "Cyrillic_zhe", XKB_KEY_Cyrillic_zhe }, - { "Cyrillic_ve", XKB_KEY_Cyrillic_ve }, - { "Cyrillic_softsign", XKB_KEY_Cyrillic_softsign }, - { "Cyrillic_yeru", XKB_KEY_Cyrillic_yeru }, - { "Cyrillic_ze", XKB_KEY_Cyrillic_ze }, - { "Cyrillic_sha", XKB_KEY_Cyrillic_sha }, - { "Cyrillic_e", XKB_KEY_Cyrillic_e }, - { "Cyrillic_shcha", XKB_KEY_Cyrillic_shcha }, - { "Cyrillic_che", XKB_KEY_Cyrillic_che }, - { "Cyrillic_hardsign", XKB_KEY_Cyrillic_hardsign }, - { "Cyrillic_YU", XKB_KEY_Cyrillic_YU }, - { "Cyrillic_A", XKB_KEY_Cyrillic_A }, - { "Cyrillic_BE", XKB_KEY_Cyrillic_BE }, - { "Cyrillic_TSE", XKB_KEY_Cyrillic_TSE }, - { "Cyrillic_DE", XKB_KEY_Cyrillic_DE }, - { "Cyrillic_IE", XKB_KEY_Cyrillic_IE }, - { "Cyrillic_EF", XKB_KEY_Cyrillic_EF }, - { "Cyrillic_GHE", XKB_KEY_Cyrillic_GHE }, - { "Cyrillic_HA", XKB_KEY_Cyrillic_HA }, - { "Cyrillic_I", XKB_KEY_Cyrillic_I }, - { "Cyrillic_SHORTI", XKB_KEY_Cyrillic_SHORTI }, - { "Cyrillic_KA", XKB_KEY_Cyrillic_KA }, - { "Cyrillic_EL", XKB_KEY_Cyrillic_EL }, - { "Cyrillic_EM", XKB_KEY_Cyrillic_EM }, - { "Cyrillic_EN", XKB_KEY_Cyrillic_EN }, - { "Cyrillic_O", XKB_KEY_Cyrillic_O }, - { "Cyrillic_PE", XKB_KEY_Cyrillic_PE }, - { "Cyrillic_YA", XKB_KEY_Cyrillic_YA }, - { "Cyrillic_ER", XKB_KEY_Cyrillic_ER }, - { "Cyrillic_ES", XKB_KEY_Cyrillic_ES }, - { "Cyrillic_TE", XKB_KEY_Cyrillic_TE }, - { "Cyrillic_U", XKB_KEY_Cyrillic_U }, - { "Cyrillic_ZHE", XKB_KEY_Cyrillic_ZHE }, - { "Cyrillic_VE", XKB_KEY_Cyrillic_VE }, - { "Cyrillic_SOFTSIGN", XKB_KEY_Cyrillic_SOFTSIGN }, - { "Cyrillic_YERU", XKB_KEY_Cyrillic_YERU }, - { "Cyrillic_ZE", XKB_KEY_Cyrillic_ZE }, - { "Cyrillic_SHA", XKB_KEY_Cyrillic_SHA }, - { "Cyrillic_E", XKB_KEY_Cyrillic_E }, - { "Cyrillic_SHCHA", XKB_KEY_Cyrillic_SHCHA }, - { "Cyrillic_CHE", XKB_KEY_Cyrillic_CHE }, - { "Cyrillic_HARDSIGN", XKB_KEY_Cyrillic_HARDSIGN }, - { "Greek_ALPHAaccent", XKB_KEY_Greek_ALPHAaccent }, - { "Greek_EPSILONaccent", XKB_KEY_Greek_EPSILONaccent }, - { "Greek_ETAaccent", XKB_KEY_Greek_ETAaccent }, - { "Greek_IOTAaccent", XKB_KEY_Greek_IOTAaccent }, - { "Greek_IOTAdieresis", XKB_KEY_Greek_IOTAdieresis }, - { "Greek_OMICRONaccent", XKB_KEY_Greek_OMICRONaccent }, - { "Greek_UPSILONaccent", XKB_KEY_Greek_UPSILONaccent }, - { "Greek_UPSILONdieresis", XKB_KEY_Greek_UPSILONdieresis }, - { "Greek_OMEGAaccent", XKB_KEY_Greek_OMEGAaccent }, - { "Greek_accentdieresis", XKB_KEY_Greek_accentdieresis }, - { "Greek_horizbar", XKB_KEY_Greek_horizbar }, - { "Greek_alphaaccent", XKB_KEY_Greek_alphaaccent }, - { "Greek_epsilonaccent", XKB_KEY_Greek_epsilonaccent }, - { "Greek_etaaccent", XKB_KEY_Greek_etaaccent }, - { "Greek_iotaaccent", XKB_KEY_Greek_iotaaccent }, - { "Greek_iotadieresis", XKB_KEY_Greek_iotadieresis }, - { "Greek_iotaaccentdieresis", XKB_KEY_Greek_iotaaccentdieresis }, - { "Greek_omicronaccent", XKB_KEY_Greek_omicronaccent }, - { "Greek_upsilonaccent", XKB_KEY_Greek_upsilonaccent }, - { "Greek_upsilondieresis", XKB_KEY_Greek_upsilondieresis }, - { "Greek_upsilonaccentdieresis", XKB_KEY_Greek_upsilonaccentdieresis }, - { "Greek_omegaaccent", XKB_KEY_Greek_omegaaccent }, - { "Greek_ALPHA", XKB_KEY_Greek_ALPHA }, - { "Greek_BETA", XKB_KEY_Greek_BETA }, - { "Greek_GAMMA", XKB_KEY_Greek_GAMMA }, - { "Greek_DELTA", XKB_KEY_Greek_DELTA }, - { "Greek_EPSILON", XKB_KEY_Greek_EPSILON }, - { "Greek_ZETA", XKB_KEY_Greek_ZETA }, - { "Greek_ETA", XKB_KEY_Greek_ETA }, - { "Greek_THETA", XKB_KEY_Greek_THETA }, - { "Greek_IOTA", XKB_KEY_Greek_IOTA }, - { "Greek_KAPPA", XKB_KEY_Greek_KAPPA }, - { "Greek_LAMDA", XKB_KEY_Greek_LAMDA }, - { "Greek_MU", XKB_KEY_Greek_MU }, - { "Greek_NU", XKB_KEY_Greek_NU }, - { "Greek_XI", XKB_KEY_Greek_XI }, - { "Greek_OMICRON", XKB_KEY_Greek_OMICRON }, - { "Greek_PI", XKB_KEY_Greek_PI }, - { "Greek_RHO", XKB_KEY_Greek_RHO }, - { "Greek_SIGMA", XKB_KEY_Greek_SIGMA }, - { "Greek_TAU", XKB_KEY_Greek_TAU }, - { "Greek_UPSILON", XKB_KEY_Greek_UPSILON }, - { "Greek_PHI", XKB_KEY_Greek_PHI }, - { "Greek_CHI", XKB_KEY_Greek_CHI }, - { "Greek_PSI", XKB_KEY_Greek_PSI }, - { "Greek_OMEGA", XKB_KEY_Greek_OMEGA }, - { "Greek_alpha", XKB_KEY_Greek_alpha }, - { "Greek_beta", XKB_KEY_Greek_beta }, - { "Greek_gamma", XKB_KEY_Greek_gamma }, - { "Greek_delta", XKB_KEY_Greek_delta }, - { "Greek_epsilon", XKB_KEY_Greek_epsilon }, - { "Greek_zeta", XKB_KEY_Greek_zeta }, - { "Greek_eta", XKB_KEY_Greek_eta }, - { "Greek_theta", XKB_KEY_Greek_theta }, - { "Greek_iota", XKB_KEY_Greek_iota }, - { "Greek_kappa", XKB_KEY_Greek_kappa }, - { "Greek_lamda", XKB_KEY_Greek_lamda }, - { "Greek_mu", XKB_KEY_Greek_mu }, - { "Greek_nu", XKB_KEY_Greek_nu }, - { "Greek_xi", XKB_KEY_Greek_xi }, - { "Greek_omicron", XKB_KEY_Greek_omicron }, - { "Greek_pi", XKB_KEY_Greek_pi }, - { "Greek_rho", XKB_KEY_Greek_rho }, - { "Greek_sigma", XKB_KEY_Greek_sigma }, - { "Greek_finalsmallsigma", XKB_KEY_Greek_finalsmallsigma }, - { "Greek_tau", XKB_KEY_Greek_tau }, - { "Greek_upsilon", XKB_KEY_Greek_upsilon }, - { "Greek_phi", XKB_KEY_Greek_phi }, - { "Greek_chi", XKB_KEY_Greek_chi }, - { "Greek_psi", XKB_KEY_Greek_psi }, - { "Greek_omega", XKB_KEY_Greek_omega }, - { "leftradical", XKB_KEY_leftradical }, - { "topleftradical", XKB_KEY_topleftradical }, - { "horizconnector", XKB_KEY_horizconnector }, - { "topintegral", XKB_KEY_topintegral }, - { "botintegral", XKB_KEY_botintegral }, - { "vertconnector", XKB_KEY_vertconnector }, - { "topleftsqbracket", XKB_KEY_topleftsqbracket }, - { "botleftsqbracket", XKB_KEY_botleftsqbracket }, - { "toprightsqbracket", XKB_KEY_toprightsqbracket }, - { "botrightsqbracket", XKB_KEY_botrightsqbracket }, - { "topleftparens", XKB_KEY_topleftparens }, - { "botleftparens", XKB_KEY_botleftparens }, - { "toprightparens", XKB_KEY_toprightparens }, - { "botrightparens", XKB_KEY_botrightparens }, - { "leftmiddlecurlybrace", XKB_KEY_leftmiddlecurlybrace }, - { "rightmiddlecurlybrace", XKB_KEY_rightmiddlecurlybrace }, - { "topleftsummation", XKB_KEY_topleftsummation }, - { "botleftsummation", XKB_KEY_botleftsummation }, - { "topvertsummationconnector", XKB_KEY_topvertsummationconnector }, - { "botvertsummationconnector", XKB_KEY_botvertsummationconnector }, - { "toprightsummation", XKB_KEY_toprightsummation }, - { "botrightsummation", XKB_KEY_botrightsummation }, - { "rightmiddlesummation", XKB_KEY_rightmiddlesummation }, - { "lessthanequal", XKB_KEY_lessthanequal }, - { "notequal", XKB_KEY_notequal }, - { "greaterthanequal", XKB_KEY_greaterthanequal }, - { "integral", XKB_KEY_integral }, - { "therefore", XKB_KEY_therefore }, - { "variation", XKB_KEY_variation }, - { "infinity", XKB_KEY_infinity }, - { "nabla", XKB_KEY_nabla }, - { "approximate", XKB_KEY_approximate }, - { "similarequal", XKB_KEY_similarequal }, - { "ifonlyif", XKB_KEY_ifonlyif }, - { "implies", XKB_KEY_implies }, - { "identical", XKB_KEY_identical }, - { "radical", XKB_KEY_radical }, - { "includedin", XKB_KEY_includedin }, - { "includes", XKB_KEY_includes }, - { "intersection", XKB_KEY_intersection }, - { "union", XKB_KEY_union }, - { "logicaland", XKB_KEY_logicaland }, - { "logicalor", XKB_KEY_logicalor }, - { "partialderivative", XKB_KEY_partialderivative }, - { "function", XKB_KEY_function }, - { "leftarrow", XKB_KEY_leftarrow }, - { "uparrow", XKB_KEY_uparrow }, - { "rightarrow", XKB_KEY_rightarrow }, - { "downarrow", XKB_KEY_downarrow }, - { "blank", XKB_KEY_blank }, - { "soliddiamond", XKB_KEY_soliddiamond }, - { "checkerboard", XKB_KEY_checkerboard }, - { "ht", XKB_KEY_ht }, - { "ff", XKB_KEY_ff }, - { "cr", XKB_KEY_cr }, - { "lf", XKB_KEY_lf }, - { "nl", XKB_KEY_nl }, - { "vt", XKB_KEY_vt }, - { "lowrightcorner", XKB_KEY_lowrightcorner }, - { "uprightcorner", XKB_KEY_uprightcorner }, - { "upleftcorner", XKB_KEY_upleftcorner }, - { "lowleftcorner", XKB_KEY_lowleftcorner }, - { "crossinglines", XKB_KEY_crossinglines }, - { "horizlinescan1", XKB_KEY_horizlinescan1 }, - { "horizlinescan3", XKB_KEY_horizlinescan3 }, - { "horizlinescan5", XKB_KEY_horizlinescan5 }, - { "horizlinescan7", XKB_KEY_horizlinescan7 }, - { "horizlinescan9", XKB_KEY_horizlinescan9 }, - { "leftt", XKB_KEY_leftt }, - { "rightt", XKB_KEY_rightt }, - { "bott", XKB_KEY_bott }, - { "topt", XKB_KEY_topt }, - { "vertbar", XKB_KEY_vertbar }, - { "emspace", XKB_KEY_emspace }, - { "enspace", XKB_KEY_enspace }, - { "em3space", XKB_KEY_em3space }, - { "em4space", XKB_KEY_em4space }, - { "digitspace", XKB_KEY_digitspace }, - { "punctspace", XKB_KEY_punctspace }, - { "thinspace", XKB_KEY_thinspace }, - { "hairspace", XKB_KEY_hairspace }, - { "emdash", XKB_KEY_emdash }, - { "endash", XKB_KEY_endash }, - { "signifblank", XKB_KEY_signifblank }, - { "ellipsis", XKB_KEY_ellipsis }, - { "doubbaselinedot", XKB_KEY_doubbaselinedot }, - { "onethird", XKB_KEY_onethird }, - { "twothirds", XKB_KEY_twothirds }, - { "onefifth", XKB_KEY_onefifth }, - { "twofifths", XKB_KEY_twofifths }, - { "threefifths", XKB_KEY_threefifths }, - { "fourfifths", XKB_KEY_fourfifths }, - { "onesixth", XKB_KEY_onesixth }, - { "fivesixths", XKB_KEY_fivesixths }, - { "careof", XKB_KEY_careof }, - { "figdash", XKB_KEY_figdash }, - { "leftanglebracket", XKB_KEY_leftanglebracket }, - { "decimalpoint", XKB_KEY_decimalpoint }, - { "rightanglebracket", XKB_KEY_rightanglebracket }, - { "marker", XKB_KEY_marker }, - { "oneeighth", XKB_KEY_oneeighth }, - { "threeeighths", XKB_KEY_threeeighths }, - { "fiveeighths", XKB_KEY_fiveeighths }, - { "seveneighths", XKB_KEY_seveneighths }, - { "trademark", XKB_KEY_trademark }, - { "signaturemark", XKB_KEY_signaturemark }, - { "trademarkincircle", XKB_KEY_trademarkincircle }, - { "leftopentriangle", XKB_KEY_leftopentriangle }, - { "rightopentriangle", XKB_KEY_rightopentriangle }, - { "emopencircle", XKB_KEY_emopencircle }, - { "emopenrectangle", XKB_KEY_emopenrectangle }, - { "leftsinglequotemark", XKB_KEY_leftsinglequotemark }, - { "rightsinglequotemark", XKB_KEY_rightsinglequotemark }, - { "leftdoublequotemark", XKB_KEY_leftdoublequotemark }, - { "rightdoublequotemark", XKB_KEY_rightdoublequotemark }, - { "prescription", XKB_KEY_prescription }, - { "permille", XKB_KEY_permille }, - { "minutes", XKB_KEY_minutes }, - { "seconds", XKB_KEY_seconds }, - { "latincross", XKB_KEY_latincross }, - { "hexagram", XKB_KEY_hexagram }, - { "filledrectbullet", XKB_KEY_filledrectbullet }, - { "filledlefttribullet", XKB_KEY_filledlefttribullet }, - { "filledrighttribullet", XKB_KEY_filledrighttribullet }, - { "emfilledcircle", XKB_KEY_emfilledcircle }, - { "emfilledrect", XKB_KEY_emfilledrect }, - { "enopencircbullet", XKB_KEY_enopencircbullet }, - { "enopensquarebullet", XKB_KEY_enopensquarebullet }, - { "openrectbullet", XKB_KEY_openrectbullet }, - { "opentribulletup", XKB_KEY_opentribulletup }, - { "opentribulletdown", XKB_KEY_opentribulletdown }, - { "openstar", XKB_KEY_openstar }, - { "enfilledcircbullet", XKB_KEY_enfilledcircbullet }, - { "enfilledsqbullet", XKB_KEY_enfilledsqbullet }, - { "filledtribulletup", XKB_KEY_filledtribulletup }, - { "filledtribulletdown", XKB_KEY_filledtribulletdown }, - { "leftpointer", XKB_KEY_leftpointer }, - { "rightpointer", XKB_KEY_rightpointer }, - { "club", XKB_KEY_club }, - { "diamond", XKB_KEY_diamond }, - { "heart", XKB_KEY_heart }, - { "maltesecross", XKB_KEY_maltesecross }, - { "dagger", XKB_KEY_dagger }, - { "doubledagger", XKB_KEY_doubledagger }, - { "checkmark", XKB_KEY_checkmark }, - { "ballotcross", XKB_KEY_ballotcross }, - { "musicalsharp", XKB_KEY_musicalsharp }, - { "musicalflat", XKB_KEY_musicalflat }, - { "malesymbol", XKB_KEY_malesymbol }, - { "femalesymbol", XKB_KEY_femalesymbol }, - { "telephone", XKB_KEY_telephone }, - { "telephonerecorder", XKB_KEY_telephonerecorder }, - { "phonographcopyright", XKB_KEY_phonographcopyright }, - { "caret", XKB_KEY_caret }, - { "singlelowquotemark", XKB_KEY_singlelowquotemark }, - { "doublelowquotemark", XKB_KEY_doublelowquotemark }, - { "cursor", XKB_KEY_cursor }, - { "leftcaret", XKB_KEY_leftcaret }, - { "rightcaret", XKB_KEY_rightcaret }, - { "downcaret", XKB_KEY_downcaret }, - { "upcaret", XKB_KEY_upcaret }, - { "overbar", XKB_KEY_overbar }, - { "downtack", XKB_KEY_downtack }, - { "upshoe", XKB_KEY_upshoe }, - { "downstile", XKB_KEY_downstile }, - { "underbar", XKB_KEY_underbar }, - { "jot", XKB_KEY_jot }, - { "quad", XKB_KEY_quad }, - { "uptack", XKB_KEY_uptack }, - { "circle", XKB_KEY_circle }, - { "upstile", XKB_KEY_upstile }, - { "downshoe", XKB_KEY_downshoe }, - { "rightshoe", XKB_KEY_rightshoe }, - { "leftshoe", XKB_KEY_leftshoe }, - { "lefttack", XKB_KEY_lefttack }, - { "righttack", XKB_KEY_righttack }, - { "hebrew_doublelowline", XKB_KEY_hebrew_doublelowline }, - { "hebrew_aleph", XKB_KEY_hebrew_aleph }, - { "hebrew_bet", XKB_KEY_hebrew_bet }, - { "hebrew_gimel", XKB_KEY_hebrew_gimel }, - { "hebrew_dalet", XKB_KEY_hebrew_dalet }, - { "hebrew_he", XKB_KEY_hebrew_he }, - { "hebrew_waw", XKB_KEY_hebrew_waw }, - { "hebrew_zain", XKB_KEY_hebrew_zain }, - { "hebrew_chet", XKB_KEY_hebrew_chet }, - { "hebrew_tet", XKB_KEY_hebrew_tet }, - { "hebrew_yod", XKB_KEY_hebrew_yod }, - { "hebrew_finalkaph", XKB_KEY_hebrew_finalkaph }, - { "hebrew_kaph", XKB_KEY_hebrew_kaph }, - { "hebrew_lamed", XKB_KEY_hebrew_lamed }, - { "hebrew_finalmem", XKB_KEY_hebrew_finalmem }, - { "hebrew_mem", XKB_KEY_hebrew_mem }, - { "hebrew_finalnun", XKB_KEY_hebrew_finalnun }, - { "hebrew_nun", XKB_KEY_hebrew_nun }, - { "hebrew_samech", XKB_KEY_hebrew_samech }, - { "hebrew_ayin", XKB_KEY_hebrew_ayin }, - { "hebrew_finalpe", XKB_KEY_hebrew_finalpe }, - { "hebrew_pe", XKB_KEY_hebrew_pe }, - { "hebrew_finalzade", XKB_KEY_hebrew_finalzade }, - { "hebrew_zade", XKB_KEY_hebrew_zade }, - { "hebrew_qoph", XKB_KEY_hebrew_qoph }, - { "hebrew_resh", XKB_KEY_hebrew_resh }, - { "hebrew_shin", XKB_KEY_hebrew_shin }, - { "hebrew_taw", XKB_KEY_hebrew_taw }, - { "Thai_kokai", XKB_KEY_Thai_kokai }, - { "Thai_khokhai", XKB_KEY_Thai_khokhai }, - { "Thai_khokhuat", XKB_KEY_Thai_khokhuat }, - { "Thai_khokhwai", XKB_KEY_Thai_khokhwai }, - { "Thai_khokhon", XKB_KEY_Thai_khokhon }, - { "Thai_khorakhang", XKB_KEY_Thai_khorakhang }, - { "Thai_ngongu", XKB_KEY_Thai_ngongu }, - { "Thai_chochan", XKB_KEY_Thai_chochan }, - { "Thai_choching", XKB_KEY_Thai_choching }, - { "Thai_chochang", XKB_KEY_Thai_chochang }, - { "Thai_soso", XKB_KEY_Thai_soso }, - { "Thai_chochoe", XKB_KEY_Thai_chochoe }, - { "Thai_yoying", XKB_KEY_Thai_yoying }, - { "Thai_dochada", XKB_KEY_Thai_dochada }, - { "Thai_topatak", XKB_KEY_Thai_topatak }, - { "Thai_thothan", XKB_KEY_Thai_thothan }, - { "Thai_thonangmontho", XKB_KEY_Thai_thonangmontho }, - { "Thai_thophuthao", XKB_KEY_Thai_thophuthao }, - { "Thai_nonen", XKB_KEY_Thai_nonen }, - { "Thai_dodek", XKB_KEY_Thai_dodek }, - { "Thai_totao", XKB_KEY_Thai_totao }, - { "Thai_thothung", XKB_KEY_Thai_thothung }, - { "Thai_thothahan", XKB_KEY_Thai_thothahan }, - { "Thai_thothong", XKB_KEY_Thai_thothong }, - { "Thai_nonu", XKB_KEY_Thai_nonu }, - { "Thai_bobaimai", XKB_KEY_Thai_bobaimai }, - { "Thai_popla", XKB_KEY_Thai_popla }, - { "Thai_phophung", XKB_KEY_Thai_phophung }, - { "Thai_fofa", XKB_KEY_Thai_fofa }, - { "Thai_phophan", XKB_KEY_Thai_phophan }, - { "Thai_fofan", XKB_KEY_Thai_fofan }, - { "Thai_phosamphao", XKB_KEY_Thai_phosamphao }, - { "Thai_moma", XKB_KEY_Thai_moma }, - { "Thai_yoyak", XKB_KEY_Thai_yoyak }, - { "Thai_rorua", XKB_KEY_Thai_rorua }, - { "Thai_ru", XKB_KEY_Thai_ru }, - { "Thai_loling", XKB_KEY_Thai_loling }, - { "Thai_lu", XKB_KEY_Thai_lu }, - { "Thai_wowaen", XKB_KEY_Thai_wowaen }, - { "Thai_sosala", XKB_KEY_Thai_sosala }, - { "Thai_sorusi", XKB_KEY_Thai_sorusi }, - { "Thai_sosua", XKB_KEY_Thai_sosua }, - { "Thai_hohip", XKB_KEY_Thai_hohip }, - { "Thai_lochula", XKB_KEY_Thai_lochula }, - { "Thai_oang", XKB_KEY_Thai_oang }, - { "Thai_honokhuk", XKB_KEY_Thai_honokhuk }, - { "Thai_paiyannoi", XKB_KEY_Thai_paiyannoi }, - { "Thai_saraa", XKB_KEY_Thai_saraa }, - { "Thai_maihanakat", XKB_KEY_Thai_maihanakat }, - { "Thai_saraaa", XKB_KEY_Thai_saraaa }, - { "Thai_saraam", XKB_KEY_Thai_saraam }, - { "Thai_sarai", XKB_KEY_Thai_sarai }, - { "Thai_saraii", XKB_KEY_Thai_saraii }, - { "Thai_saraue", XKB_KEY_Thai_saraue }, - { "Thai_sarauee", XKB_KEY_Thai_sarauee }, - { "Thai_sarau", XKB_KEY_Thai_sarau }, - { "Thai_sarauu", XKB_KEY_Thai_sarauu }, - { "Thai_phinthu", XKB_KEY_Thai_phinthu }, - { "Thai_maihanakat_maitho", XKB_KEY_Thai_maihanakat_maitho }, - { "Thai_baht", XKB_KEY_Thai_baht }, - { "Thai_sarae", XKB_KEY_Thai_sarae }, - { "Thai_saraae", XKB_KEY_Thai_saraae }, - { "Thai_sarao", XKB_KEY_Thai_sarao }, - { "Thai_saraaimaimuan", XKB_KEY_Thai_saraaimaimuan }, - { "Thai_saraaimaimalai", XKB_KEY_Thai_saraaimaimalai }, - { "Thai_lakkhangyao", XKB_KEY_Thai_lakkhangyao }, - { "Thai_maiyamok", XKB_KEY_Thai_maiyamok }, - { "Thai_maitaikhu", XKB_KEY_Thai_maitaikhu }, - { "Thai_maiek", XKB_KEY_Thai_maiek }, - { "Thai_maitho", XKB_KEY_Thai_maitho }, - { "Thai_maitri", XKB_KEY_Thai_maitri }, - { "Thai_maichattawa", XKB_KEY_Thai_maichattawa }, - { "Thai_thanthakhat", XKB_KEY_Thai_thanthakhat }, - { "Thai_nikhahit", XKB_KEY_Thai_nikhahit }, - { "Thai_leksun", XKB_KEY_Thai_leksun }, - { "Thai_leknung", XKB_KEY_Thai_leknung }, - { "Thai_leksong", XKB_KEY_Thai_leksong }, - { "Thai_leksam", XKB_KEY_Thai_leksam }, - { "Thai_leksi", XKB_KEY_Thai_leksi }, - { "Thai_lekha", XKB_KEY_Thai_lekha }, - { "Thai_lekhok", XKB_KEY_Thai_lekhok }, - { "Thai_lekchet", XKB_KEY_Thai_lekchet }, - { "Thai_lekpaet", XKB_KEY_Thai_lekpaet }, - { "Thai_lekkao", XKB_KEY_Thai_lekkao }, - { "Hangul_Kiyeog", XKB_KEY_Hangul_Kiyeog }, - { "Hangul_SsangKiyeog", XKB_KEY_Hangul_SsangKiyeog }, - { "Hangul_KiyeogSios", XKB_KEY_Hangul_KiyeogSios }, - { "Hangul_Nieun", XKB_KEY_Hangul_Nieun }, - { "Hangul_NieunJieuj", XKB_KEY_Hangul_NieunJieuj }, - { "Hangul_NieunHieuh", XKB_KEY_Hangul_NieunHieuh }, - { "Hangul_Dikeud", XKB_KEY_Hangul_Dikeud }, - { "Hangul_SsangDikeud", XKB_KEY_Hangul_SsangDikeud }, - { "Hangul_Rieul", XKB_KEY_Hangul_Rieul }, - { "Hangul_RieulKiyeog", XKB_KEY_Hangul_RieulKiyeog }, - { "Hangul_RieulMieum", XKB_KEY_Hangul_RieulMieum }, - { "Hangul_RieulPieub", XKB_KEY_Hangul_RieulPieub }, - { "Hangul_RieulSios", XKB_KEY_Hangul_RieulSios }, - { "Hangul_RieulTieut", XKB_KEY_Hangul_RieulTieut }, - { "Hangul_RieulPhieuf", XKB_KEY_Hangul_RieulPhieuf }, - { "Hangul_RieulHieuh", XKB_KEY_Hangul_RieulHieuh }, - { "Hangul_Mieum", XKB_KEY_Hangul_Mieum }, - { "Hangul_Pieub", XKB_KEY_Hangul_Pieub }, - { "Hangul_SsangPieub", XKB_KEY_Hangul_SsangPieub }, - { "Hangul_PieubSios", XKB_KEY_Hangul_PieubSios }, - { "Hangul_Sios", XKB_KEY_Hangul_Sios }, - { "Hangul_SsangSios", XKB_KEY_Hangul_SsangSios }, - { "Hangul_Ieung", XKB_KEY_Hangul_Ieung }, - { "Hangul_Jieuj", XKB_KEY_Hangul_Jieuj }, - { "Hangul_SsangJieuj", XKB_KEY_Hangul_SsangJieuj }, - { "Hangul_Cieuc", XKB_KEY_Hangul_Cieuc }, - { "Hangul_Khieuq", XKB_KEY_Hangul_Khieuq }, - { "Hangul_Tieut", XKB_KEY_Hangul_Tieut }, - { "Hangul_Phieuf", XKB_KEY_Hangul_Phieuf }, - { "Hangul_Hieuh", XKB_KEY_Hangul_Hieuh }, - { "Hangul_A", XKB_KEY_Hangul_A }, - { "Hangul_AE", XKB_KEY_Hangul_AE }, - { "Hangul_YA", XKB_KEY_Hangul_YA }, - { "Hangul_YAE", XKB_KEY_Hangul_YAE }, - { "Hangul_EO", XKB_KEY_Hangul_EO }, - { "Hangul_E", XKB_KEY_Hangul_E }, - { "Hangul_YEO", XKB_KEY_Hangul_YEO }, - { "Hangul_YE", XKB_KEY_Hangul_YE }, - { "Hangul_O", XKB_KEY_Hangul_O }, - { "Hangul_WA", XKB_KEY_Hangul_WA }, - { "Hangul_WAE", XKB_KEY_Hangul_WAE }, - { "Hangul_OE", XKB_KEY_Hangul_OE }, - { "Hangul_YO", XKB_KEY_Hangul_YO }, - { "Hangul_U", XKB_KEY_Hangul_U }, - { "Hangul_WEO", XKB_KEY_Hangul_WEO }, - { "Hangul_WE", XKB_KEY_Hangul_WE }, - { "Hangul_WI", XKB_KEY_Hangul_WI }, - { "Hangul_YU", XKB_KEY_Hangul_YU }, - { "Hangul_EU", XKB_KEY_Hangul_EU }, - { "Hangul_YI", XKB_KEY_Hangul_YI }, - { "Hangul_I", XKB_KEY_Hangul_I }, - { "Hangul_J_Kiyeog", XKB_KEY_Hangul_J_Kiyeog }, - { "Hangul_J_SsangKiyeog", XKB_KEY_Hangul_J_SsangKiyeog }, - { "Hangul_J_KiyeogSios", XKB_KEY_Hangul_J_KiyeogSios }, - { "Hangul_J_Nieun", XKB_KEY_Hangul_J_Nieun }, - { "Hangul_J_NieunJieuj", XKB_KEY_Hangul_J_NieunJieuj }, - { "Hangul_J_NieunHieuh", XKB_KEY_Hangul_J_NieunHieuh }, - { "Hangul_J_Dikeud", XKB_KEY_Hangul_J_Dikeud }, - { "Hangul_J_Rieul", XKB_KEY_Hangul_J_Rieul }, - { "Hangul_J_RieulKiyeog", XKB_KEY_Hangul_J_RieulKiyeog }, - { "Hangul_J_RieulMieum", XKB_KEY_Hangul_J_RieulMieum }, - { "Hangul_J_RieulPieub", XKB_KEY_Hangul_J_RieulPieub }, - { "Hangul_J_RieulSios", XKB_KEY_Hangul_J_RieulSios }, - { "Hangul_J_RieulTieut", XKB_KEY_Hangul_J_RieulTieut }, - { "Hangul_J_RieulPhieuf", XKB_KEY_Hangul_J_RieulPhieuf }, - { "Hangul_J_RieulHieuh", XKB_KEY_Hangul_J_RieulHieuh }, - { "Hangul_J_Mieum", XKB_KEY_Hangul_J_Mieum }, - { "Hangul_J_Pieub", XKB_KEY_Hangul_J_Pieub }, - { "Hangul_J_PieubSios", XKB_KEY_Hangul_J_PieubSios }, - { "Hangul_J_Sios", XKB_KEY_Hangul_J_Sios }, - { "Hangul_J_SsangSios", XKB_KEY_Hangul_J_SsangSios }, - { "Hangul_J_Ieung", XKB_KEY_Hangul_J_Ieung }, - { "Hangul_J_Jieuj", XKB_KEY_Hangul_J_Jieuj }, - { "Hangul_J_Cieuc", XKB_KEY_Hangul_J_Cieuc }, - { "Hangul_J_Khieuq", XKB_KEY_Hangul_J_Khieuq }, - { "Hangul_J_Tieut", XKB_KEY_Hangul_J_Tieut }, - { "Hangul_J_Phieuf", XKB_KEY_Hangul_J_Phieuf }, - { "Hangul_J_Hieuh", XKB_KEY_Hangul_J_Hieuh }, - { "Hangul_RieulYeorinHieuh", XKB_KEY_Hangul_RieulYeorinHieuh }, - { "Hangul_SunkyeongeumMieum", XKB_KEY_Hangul_SunkyeongeumMieum }, - { "Hangul_SunkyeongeumPieub", XKB_KEY_Hangul_SunkyeongeumPieub }, - { "Hangul_PanSios", XKB_KEY_Hangul_PanSios }, - { "Hangul_KkogjiDalrinIeung", XKB_KEY_Hangul_KkogjiDalrinIeung }, - { "Hangul_SunkyeongeumPhieuf", XKB_KEY_Hangul_SunkyeongeumPhieuf }, - { "Hangul_YeorinHieuh", XKB_KEY_Hangul_YeorinHieuh }, - { "Hangul_AraeA", XKB_KEY_Hangul_AraeA }, - { "Hangul_AraeAE", XKB_KEY_Hangul_AraeAE }, - { "Hangul_J_PanSios", XKB_KEY_Hangul_J_PanSios }, - { "Hangul_J_KkogjiDalrinIeung", XKB_KEY_Hangul_J_KkogjiDalrinIeung }, - { "Hangul_J_YeorinHieuh", XKB_KEY_Hangul_J_YeorinHieuh }, - { "Korean_Won", XKB_KEY_Korean_Won }, - { "OE", XKB_KEY_OE }, - { "oe", XKB_KEY_oe }, - { "Ydiaeresis", XKB_KEY_Ydiaeresis }, - { "EuroSign", XKB_KEY_EuroSign }, - { "3270_Duplicate", XKB_KEY_3270_Duplicate }, - { "3270_FieldMark", XKB_KEY_3270_FieldMark }, - { "3270_Right2", XKB_KEY_3270_Right2 }, - { "3270_Left2", XKB_KEY_3270_Left2 }, - { "3270_BackTab", XKB_KEY_3270_BackTab }, - { "3270_EraseEOF", XKB_KEY_3270_EraseEOF }, - { "3270_EraseInput", XKB_KEY_3270_EraseInput }, - { "3270_Reset", XKB_KEY_3270_Reset }, - { "3270_Quit", XKB_KEY_3270_Quit }, - { "3270_PA1", XKB_KEY_3270_PA1 }, - { "3270_PA2", XKB_KEY_3270_PA2 }, - { "3270_PA3", XKB_KEY_3270_PA3 }, - { "3270_Test", XKB_KEY_3270_Test }, - { "3270_Attn", XKB_KEY_3270_Attn }, - { "3270_CursorBlink", XKB_KEY_3270_CursorBlink }, - { "3270_AltCursor", XKB_KEY_3270_AltCursor }, - { "3270_KeyClick", XKB_KEY_3270_KeyClick }, - { "3270_Jump", XKB_KEY_3270_Jump }, - { "3270_Ident", XKB_KEY_3270_Ident }, - { "3270_Rule", XKB_KEY_3270_Rule }, - { "3270_Copy", XKB_KEY_3270_Copy }, - { "3270_Play", XKB_KEY_3270_Play }, - { "3270_Setup", XKB_KEY_3270_Setup }, - { "3270_Record", XKB_KEY_3270_Record }, - { "3270_ChangeScreen", XKB_KEY_3270_ChangeScreen }, - { "3270_DeleteWord", XKB_KEY_3270_DeleteWord }, - { "3270_ExSelect", XKB_KEY_3270_ExSelect }, - { "3270_CursorSelect", XKB_KEY_3270_CursorSelect }, - { "3270_PrintScreen", XKB_KEY_3270_PrintScreen }, - { "3270_Enter", XKB_KEY_3270_Enter }, - { "ISO_Lock", XKB_KEY_ISO_Lock }, - { "ISO_Level2_Latch", XKB_KEY_ISO_Level2_Latch }, - { "ISO_Level3_Shift", XKB_KEY_ISO_Level3_Shift }, - { "ISO_Level3_Latch", XKB_KEY_ISO_Level3_Latch }, - { "ISO_Level3_Lock", XKB_KEY_ISO_Level3_Lock }, - { "ISO_Group_Latch", XKB_KEY_ISO_Group_Latch }, - { "ISO_Group_Lock", XKB_KEY_ISO_Group_Lock }, - { "ISO_Next_Group", XKB_KEY_ISO_Next_Group }, - { "ISO_Next_Group_Lock", XKB_KEY_ISO_Next_Group_Lock }, - { "ISO_Prev_Group", XKB_KEY_ISO_Prev_Group }, - { "ISO_Prev_Group_Lock", XKB_KEY_ISO_Prev_Group_Lock }, - { "ISO_First_Group", XKB_KEY_ISO_First_Group }, - { "ISO_First_Group_Lock", XKB_KEY_ISO_First_Group_Lock }, - { "ISO_Last_Group", XKB_KEY_ISO_Last_Group }, - { "ISO_Last_Group_Lock", XKB_KEY_ISO_Last_Group_Lock }, - { "ISO_Level5_Shift", XKB_KEY_ISO_Level5_Shift }, - { "ISO_Level5_Latch", XKB_KEY_ISO_Level5_Latch }, - { "ISO_Level5_Lock", XKB_KEY_ISO_Level5_Lock }, - { "ISO_Left_Tab", XKB_KEY_ISO_Left_Tab }, - { "ISO_Move_Line_Up", XKB_KEY_ISO_Move_Line_Up }, - { "ISO_Move_Line_Down", XKB_KEY_ISO_Move_Line_Down }, - { "ISO_Partial_Line_Up", XKB_KEY_ISO_Partial_Line_Up }, - { "ISO_Partial_Line_Down", XKB_KEY_ISO_Partial_Line_Down }, - { "ISO_Partial_Space_Left", XKB_KEY_ISO_Partial_Space_Left }, - { "ISO_Partial_Space_Right", XKB_KEY_ISO_Partial_Space_Right }, - { "ISO_Set_Margin_Left", XKB_KEY_ISO_Set_Margin_Left }, - { "ISO_Set_Margin_Right", XKB_KEY_ISO_Set_Margin_Right }, - { "ISO_Release_Margin_Left", XKB_KEY_ISO_Release_Margin_Left }, - { "ISO_Release_Margin_Right", XKB_KEY_ISO_Release_Margin_Right }, - { "ISO_Release_Both_Margins", XKB_KEY_ISO_Release_Both_Margins }, - { "ISO_Fast_Cursor_Left", XKB_KEY_ISO_Fast_Cursor_Left }, - { "ISO_Fast_Cursor_Right", XKB_KEY_ISO_Fast_Cursor_Right }, - { "ISO_Fast_Cursor_Up", XKB_KEY_ISO_Fast_Cursor_Up }, - { "ISO_Fast_Cursor_Down", XKB_KEY_ISO_Fast_Cursor_Down }, - { "ISO_Continuous_Underline", XKB_KEY_ISO_Continuous_Underline }, - { "ISO_Discontinuous_Underline", XKB_KEY_ISO_Discontinuous_Underline }, - { "ISO_Emphasize", XKB_KEY_ISO_Emphasize }, - { "ISO_Center_Object", XKB_KEY_ISO_Center_Object }, - { "ISO_Enter", XKB_KEY_ISO_Enter }, - { "dead_grave", XKB_KEY_dead_grave }, - { "dead_acute", XKB_KEY_dead_acute }, - { "dead_circumflex", XKB_KEY_dead_circumflex }, - { "dead_tilde", XKB_KEY_dead_tilde }, - { "dead_macron", XKB_KEY_dead_macron }, - { "dead_breve", XKB_KEY_dead_breve }, - { "dead_abovedot", XKB_KEY_dead_abovedot }, - { "dead_diaeresis", XKB_KEY_dead_diaeresis }, - { "dead_abovering", XKB_KEY_dead_abovering }, - { "dead_doubleacute", XKB_KEY_dead_doubleacute }, - { "dead_caron", XKB_KEY_dead_caron }, - { "dead_cedilla", XKB_KEY_dead_cedilla }, - { "dead_ogonek", XKB_KEY_dead_ogonek }, - { "dead_iota", XKB_KEY_dead_iota }, - { "dead_voiced_sound", XKB_KEY_dead_voiced_sound }, - { "dead_semivoiced_sound", XKB_KEY_dead_semivoiced_sound }, - { "dead_belowdot", XKB_KEY_dead_belowdot }, - { "dead_hook", XKB_KEY_dead_hook }, - { "dead_horn", XKB_KEY_dead_horn }, - { "dead_stroke", XKB_KEY_dead_stroke }, - { "dead_abovecomma", XKB_KEY_dead_abovecomma }, - { "dead_abovereversedcomma", XKB_KEY_dead_abovereversedcomma }, - { "dead_doublegrave", XKB_KEY_dead_doublegrave }, - { "dead_belowring", XKB_KEY_dead_belowring }, - { "dead_belowmacron", XKB_KEY_dead_belowmacron }, - { "dead_belowcircumflex", XKB_KEY_dead_belowcircumflex }, - { "dead_belowtilde", XKB_KEY_dead_belowtilde }, - { "dead_belowbreve", XKB_KEY_dead_belowbreve }, - { "dead_belowdiaeresis", XKB_KEY_dead_belowdiaeresis }, - { "dead_invertedbreve", XKB_KEY_dead_invertedbreve }, - { "dead_belowcomma", XKB_KEY_dead_belowcomma }, - { "dead_currency", XKB_KEY_dead_currency }, - { "AccessX_Enable", XKB_KEY_AccessX_Enable }, - { "AccessX_Feedback_Enable", XKB_KEY_AccessX_Feedback_Enable }, - { "RepeatKeys_Enable", XKB_KEY_RepeatKeys_Enable }, - { "SlowKeys_Enable", XKB_KEY_SlowKeys_Enable }, - { "BounceKeys_Enable", XKB_KEY_BounceKeys_Enable }, - { "StickyKeys_Enable", XKB_KEY_StickyKeys_Enable }, - { "MouseKeys_Enable", XKB_KEY_MouseKeys_Enable }, - { "MouseKeys_Accel_Enable", XKB_KEY_MouseKeys_Accel_Enable }, - { "Overlay1_Enable", XKB_KEY_Overlay1_Enable }, - { "Overlay2_Enable", XKB_KEY_Overlay2_Enable }, - { "AudibleBell_Enable", XKB_KEY_AudibleBell_Enable }, - { "dead_a", XKB_KEY_dead_a }, - { "dead_A", XKB_KEY_dead_A }, - { "dead_e", XKB_KEY_dead_e }, - { "dead_E", XKB_KEY_dead_E }, - { "dead_i", XKB_KEY_dead_i }, - { "dead_I", XKB_KEY_dead_I }, - { "dead_o", XKB_KEY_dead_o }, - { "dead_O", XKB_KEY_dead_O }, - { "dead_u", XKB_KEY_dead_u }, - { "dead_U", XKB_KEY_dead_U }, - { "dead_small_schwa", XKB_KEY_dead_small_schwa }, - { "dead_capital_schwa", XKB_KEY_dead_capital_schwa }, - { "dead_greek", XKB_KEY_dead_greek }, - { "ch", XKB_KEY_ch }, - { "Ch", XKB_KEY_Ch }, - { "CH", XKB_KEY_CH }, - { "c_h", XKB_KEY_c_h }, - { "C_h", XKB_KEY_C_h }, - { "C_H", XKB_KEY_C_H }, - { "First_Virtual_Screen", XKB_KEY_First_Virtual_Screen }, - { "Prev_Virtual_Screen", XKB_KEY_Prev_Virtual_Screen }, - { "Next_Virtual_Screen", XKB_KEY_Next_Virtual_Screen }, - { "Last_Virtual_Screen", XKB_KEY_Last_Virtual_Screen }, - { "Terminate_Server", XKB_KEY_Terminate_Server }, - { "Pointer_Left", XKB_KEY_Pointer_Left }, - { "Pointer_Right", XKB_KEY_Pointer_Right }, - { "Pointer_Up", XKB_KEY_Pointer_Up }, - { "Pointer_Down", XKB_KEY_Pointer_Down }, - { "Pointer_UpLeft", XKB_KEY_Pointer_UpLeft }, - { "Pointer_UpRight", XKB_KEY_Pointer_UpRight }, - { "Pointer_DownLeft", XKB_KEY_Pointer_DownLeft }, - { "Pointer_DownRight", XKB_KEY_Pointer_DownRight }, - { "Pointer_Button_Dflt", XKB_KEY_Pointer_Button_Dflt }, - { "Pointer_Button1", XKB_KEY_Pointer_Button1 }, - { "Pointer_Button2", XKB_KEY_Pointer_Button2 }, - { "Pointer_Button3", XKB_KEY_Pointer_Button3 }, - { "Pointer_Button4", XKB_KEY_Pointer_Button4 }, - { "Pointer_Button5", XKB_KEY_Pointer_Button5 }, - { "Pointer_DblClick_Dflt", XKB_KEY_Pointer_DblClick_Dflt }, - { "Pointer_DblClick1", XKB_KEY_Pointer_DblClick1 }, - { "Pointer_DblClick2", XKB_KEY_Pointer_DblClick2 }, - { "Pointer_DblClick3", XKB_KEY_Pointer_DblClick3 }, - { "Pointer_DblClick4", XKB_KEY_Pointer_DblClick4 }, - { "Pointer_DblClick5", XKB_KEY_Pointer_DblClick5 }, - { "Pointer_Drag_Dflt", XKB_KEY_Pointer_Drag_Dflt }, - { "Pointer_Drag1", XKB_KEY_Pointer_Drag1 }, - { "Pointer_Drag2", XKB_KEY_Pointer_Drag2 }, - { "Pointer_Drag3", XKB_KEY_Pointer_Drag3 }, - { "Pointer_Drag4", XKB_KEY_Pointer_Drag4 }, - { "Pointer_EnableKeys", XKB_KEY_Pointer_EnableKeys }, - { "Pointer_Accelerate", XKB_KEY_Pointer_Accelerate }, - { "Pointer_DfltBtnNext", XKB_KEY_Pointer_DfltBtnNext }, - { "Pointer_DfltBtnPrev", XKB_KEY_Pointer_DfltBtnPrev }, - { "Pointer_Drag5", XKB_KEY_Pointer_Drag5 }, - { "BackSpace", XKB_KEY_BackSpace }, - { "Tab", XKB_KEY_Tab }, - { "Linefeed", XKB_KEY_Linefeed }, - { "Clear", XKB_KEY_Clear }, - { "Return", XKB_KEY_Return }, - { "Pause", XKB_KEY_Pause }, - { "Scroll_Lock", XKB_KEY_Scroll_Lock }, - { "Sys_Req", XKB_KEY_Sys_Req }, - { "Escape", XKB_KEY_Escape }, - { "Multi_key", XKB_KEY_Multi_key }, - { "Kanji", XKB_KEY_Kanji }, - { "Muhenkan", XKB_KEY_Muhenkan }, - { "Henkan_Mode", XKB_KEY_Henkan_Mode }, - { "Romaji", XKB_KEY_Romaji }, - { "Hiragana", XKB_KEY_Hiragana }, - { "Katakana", XKB_KEY_Katakana }, - { "Hiragana_Katakana", XKB_KEY_Hiragana_Katakana }, - { "Zenkaku", XKB_KEY_Zenkaku }, - { "Hankaku", XKB_KEY_Hankaku }, - { "Zenkaku_Hankaku", XKB_KEY_Zenkaku_Hankaku }, - { "Touroku", XKB_KEY_Touroku }, - { "Massyo", XKB_KEY_Massyo }, - { "Kana_Lock", XKB_KEY_Kana_Lock }, - { "Kana_Shift", XKB_KEY_Kana_Shift }, - { "Eisu_Shift", XKB_KEY_Eisu_Shift }, - { "Eisu_toggle", XKB_KEY_Eisu_toggle }, - { "Hangul", XKB_KEY_Hangul }, - { "Hangul_Start", XKB_KEY_Hangul_Start }, - { "Hangul_End", XKB_KEY_Hangul_End }, - { "Hangul_Hanja", XKB_KEY_Hangul_Hanja }, - { "Hangul_Jamo", XKB_KEY_Hangul_Jamo }, - { "Hangul_Romaja", XKB_KEY_Hangul_Romaja }, - { "Codeinput", XKB_KEY_Codeinput }, - { "Hangul_Jeonja", XKB_KEY_Hangul_Jeonja }, - { "Hangul_Banja", XKB_KEY_Hangul_Banja }, - { "Hangul_PreHanja", XKB_KEY_Hangul_PreHanja }, - { "Hangul_PostHanja", XKB_KEY_Hangul_PostHanja }, - { "SingleCandidate", XKB_KEY_SingleCandidate }, - { "MultipleCandidate", XKB_KEY_MultipleCandidate }, - { "PreviousCandidate", XKB_KEY_PreviousCandidate }, - { "Hangul_Special", XKB_KEY_Hangul_Special }, - { "Home", XKB_KEY_Home }, - { "Left", XKB_KEY_Left }, - { "Up", XKB_KEY_Up }, - { "Right", XKB_KEY_Right }, - { "Down", XKB_KEY_Down }, - { "Prior", XKB_KEY_Prior }, - { "Next", XKB_KEY_Next }, - { "End", XKB_KEY_End }, - { "Begin", XKB_KEY_Begin }, - { "Select", XKB_KEY_Select }, - { "Print", XKB_KEY_Print }, - { "Execute", XKB_KEY_Execute }, - { "Insert", XKB_KEY_Insert }, - { "Undo", XKB_KEY_Undo }, - { "Redo", XKB_KEY_Redo }, - { "Menu", XKB_KEY_Menu }, - { "Find", XKB_KEY_Find }, - { "Cancel", XKB_KEY_Cancel }, - { "Help", XKB_KEY_Help }, - { "Break", XKB_KEY_Break }, - { "Mode_switch", XKB_KEY_Mode_switch }, - { "Num_Lock", XKB_KEY_Num_Lock }, - { "KP_Space", XKB_KEY_KP_Space }, - { "KP_Tab", XKB_KEY_KP_Tab }, - { "KP_Enter", XKB_KEY_KP_Enter }, - { "KP_F1", XKB_KEY_KP_F1 }, - { "KP_F2", XKB_KEY_KP_F2 }, - { "KP_F3", XKB_KEY_KP_F3 }, - { "KP_F4", XKB_KEY_KP_F4 }, - { "KP_Home", XKB_KEY_KP_Home }, - { "KP_Left", XKB_KEY_KP_Left }, - { "KP_Up", XKB_KEY_KP_Up }, - { "KP_Right", XKB_KEY_KP_Right }, - { "KP_Down", XKB_KEY_KP_Down }, - { "KP_Prior", XKB_KEY_KP_Prior }, - { "KP_Next", XKB_KEY_KP_Next }, - { "KP_End", XKB_KEY_KP_End }, - { "KP_Begin", XKB_KEY_KP_Begin }, - { "KP_Insert", XKB_KEY_KP_Insert }, - { "KP_Delete", XKB_KEY_KP_Delete }, - { "KP_Multiply", XKB_KEY_KP_Multiply }, - { "KP_Add", XKB_KEY_KP_Add }, - { "KP_Separator", XKB_KEY_KP_Separator }, - { "KP_Subtract", XKB_KEY_KP_Subtract }, - { "KP_Decimal", XKB_KEY_KP_Decimal }, - { "KP_Divide", XKB_KEY_KP_Divide }, - { "KP_0", XKB_KEY_KP_0 }, - { "KP_1", XKB_KEY_KP_1 }, - { "KP_2", XKB_KEY_KP_2 }, - { "KP_3", XKB_KEY_KP_3 }, - { "KP_4", XKB_KEY_KP_4 }, - { "KP_5", XKB_KEY_KP_5 }, - { "KP_6", XKB_KEY_KP_6 }, - { "KP_7", XKB_KEY_KP_7 }, - { "KP_8", XKB_KEY_KP_8 }, - { "KP_9", XKB_KEY_KP_9 }, - { "KP_Equal", XKB_KEY_KP_Equal }, - { "F1", XKB_KEY_F1 }, - { "F2", XKB_KEY_F2 }, - { "F3", XKB_KEY_F3 }, - { "F4", XKB_KEY_F4 }, - { "F5", XKB_KEY_F5 }, - { "F6", XKB_KEY_F6 }, - { "F7", XKB_KEY_F7 }, - { "F8", XKB_KEY_F8 }, - { "F9", XKB_KEY_F9 }, - { "F10", XKB_KEY_F10 }, - { "F11", XKB_KEY_F11 }, - { "F12", XKB_KEY_F12 }, - { "F13", XKB_KEY_F13 }, - { "F14", XKB_KEY_F14 }, - { "F15", XKB_KEY_F15 }, - { "F16", XKB_KEY_F16 }, - { "F17", XKB_KEY_F17 }, - { "F18", XKB_KEY_F18 }, - { "F19", XKB_KEY_F19 }, - { "F20", XKB_KEY_F20 }, - { "F21", XKB_KEY_F21 }, - { "F22", XKB_KEY_F22 }, - { "F23", XKB_KEY_F23 }, - { "F24", XKB_KEY_F24 }, - { "F25", XKB_KEY_F25 }, - { "F26", XKB_KEY_F26 }, - { "F27", XKB_KEY_F27 }, - { "F28", XKB_KEY_F28 }, - { "F29", XKB_KEY_F29 }, - { "F30", XKB_KEY_F30 }, - { "F31", XKB_KEY_F31 }, - { "F32", XKB_KEY_F32 }, - { "F33", XKB_KEY_F33 }, - { "F34", XKB_KEY_F34 }, - { "F35", XKB_KEY_F35 }, - { "Shift_L", XKB_KEY_Shift_L }, - { "Shift_R", XKB_KEY_Shift_R }, - { "Control_L", XKB_KEY_Control_L }, - { "Control_R", XKB_KEY_Control_R }, - { "Caps_Lock", XKB_KEY_Caps_Lock }, - { "Shift_Lock", XKB_KEY_Shift_Lock }, - { "Meta_L", XKB_KEY_Meta_L }, - { "Meta_R", XKB_KEY_Meta_R }, - { "Alt_L", XKB_KEY_Alt_L }, - { "Alt_R", XKB_KEY_Alt_R }, - { "Super_L", XKB_KEY_Super_L }, - { "Super_R", XKB_KEY_Super_R }, - { "Hyper_L", XKB_KEY_Hyper_L }, - { "Hyper_R", XKB_KEY_Hyper_R }, - { "braille_dot_1", XKB_KEY_braille_dot_1 }, - { "braille_dot_2", XKB_KEY_braille_dot_2 }, - { "braille_dot_3", XKB_KEY_braille_dot_3 }, - { "braille_dot_4", XKB_KEY_braille_dot_4 }, - { "braille_dot_5", XKB_KEY_braille_dot_5 }, - { "braille_dot_6", XKB_KEY_braille_dot_6 }, - { "braille_dot_7", XKB_KEY_braille_dot_7 }, - { "braille_dot_8", XKB_KEY_braille_dot_8 }, - { "braille_dot_9", XKB_KEY_braille_dot_9 }, - { "braille_dot_10", XKB_KEY_braille_dot_10 }, - { "Delete", XKB_KEY_Delete }, - { "VoidSymbol", XKB_KEY_VoidSymbol }, - { "Ibreve", XKB_KEY_Ibreve }, - { "ibreve", XKB_KEY_ibreve }, - { "Wcircumflex", XKB_KEY_Wcircumflex }, - { "wcircumflex", XKB_KEY_wcircumflex }, - { "Ycircumflex", XKB_KEY_Ycircumflex }, - { "ycircumflex", XKB_KEY_ycircumflex }, - { "SCHWA", XKB_KEY_SCHWA }, - { "Obarred", XKB_KEY_Obarred }, - { "Ohorn", XKB_KEY_Ohorn }, - { "ohorn", XKB_KEY_ohorn }, - { "Uhorn", XKB_KEY_Uhorn }, - { "uhorn", XKB_KEY_uhorn }, - { "Zstroke", XKB_KEY_Zstroke }, - { "zstroke", XKB_KEY_zstroke }, - { "EZH", XKB_KEY_EZH }, - { "Ocaron", XKB_KEY_Ocaron }, - { "ocaron", XKB_KEY_ocaron }, - { "Gcaron", XKB_KEY_Gcaron }, - { "gcaron", XKB_KEY_gcaron }, - { "schwa", XKB_KEY_schwa }, - { "obarred", XKB_KEY_obarred }, - { "ezh", XKB_KEY_ezh }, - { "Cyrillic_GHE_bar", XKB_KEY_Cyrillic_GHE_bar }, - { "Cyrillic_ghe_bar", XKB_KEY_Cyrillic_ghe_bar }, - { "Cyrillic_ZHE_descender", XKB_KEY_Cyrillic_ZHE_descender }, - { "Cyrillic_zhe_descender", XKB_KEY_Cyrillic_zhe_descender }, - { "Cyrillic_KA_descender", XKB_KEY_Cyrillic_KA_descender }, - { "Cyrillic_ka_descender", XKB_KEY_Cyrillic_ka_descender }, - { "Cyrillic_KA_vertstroke", XKB_KEY_Cyrillic_KA_vertstroke }, - { "Cyrillic_ka_vertstroke", XKB_KEY_Cyrillic_ka_vertstroke }, - { "Cyrillic_EN_descender", XKB_KEY_Cyrillic_EN_descender }, - { "Cyrillic_en_descender", XKB_KEY_Cyrillic_en_descender }, - { "Cyrillic_U_straight", XKB_KEY_Cyrillic_U_straight }, - { "Cyrillic_u_straight", XKB_KEY_Cyrillic_u_straight }, - { "Cyrillic_U_straight_bar", XKB_KEY_Cyrillic_U_straight_bar }, - { "Cyrillic_u_straight_bar", XKB_KEY_Cyrillic_u_straight_bar }, - { "Cyrillic_HA_descender", XKB_KEY_Cyrillic_HA_descender }, - { "Cyrillic_ha_descender", XKB_KEY_Cyrillic_ha_descender }, - { "Cyrillic_CHE_descender", XKB_KEY_Cyrillic_CHE_descender }, - { "Cyrillic_che_descender", XKB_KEY_Cyrillic_che_descender }, - { "Cyrillic_CHE_vertstroke", XKB_KEY_Cyrillic_CHE_vertstroke }, - { "Cyrillic_che_vertstroke", XKB_KEY_Cyrillic_che_vertstroke }, - { "Cyrillic_SHHA", XKB_KEY_Cyrillic_SHHA }, - { "Cyrillic_shha", XKB_KEY_Cyrillic_shha }, - { "Cyrillic_SCHWA", XKB_KEY_Cyrillic_SCHWA }, - { "Cyrillic_schwa", XKB_KEY_Cyrillic_schwa }, - { "Cyrillic_I_macron", XKB_KEY_Cyrillic_I_macron }, - { "Cyrillic_i_macron", XKB_KEY_Cyrillic_i_macron }, - { "Cyrillic_O_bar", XKB_KEY_Cyrillic_O_bar }, - { "Cyrillic_o_bar", XKB_KEY_Cyrillic_o_bar }, - { "Cyrillic_U_macron", XKB_KEY_Cyrillic_U_macron }, - { "Cyrillic_u_macron", XKB_KEY_Cyrillic_u_macron }, - { "Armenian_AYB", XKB_KEY_Armenian_AYB }, - { "Armenian_BEN", XKB_KEY_Armenian_BEN }, - { "Armenian_GIM", XKB_KEY_Armenian_GIM }, - { "Armenian_DA", XKB_KEY_Armenian_DA }, - { "Armenian_YECH", XKB_KEY_Armenian_YECH }, - { "Armenian_ZA", XKB_KEY_Armenian_ZA }, - { "Armenian_E", XKB_KEY_Armenian_E }, - { "Armenian_AT", XKB_KEY_Armenian_AT }, - { "Armenian_TO", XKB_KEY_Armenian_TO }, - { "Armenian_ZHE", XKB_KEY_Armenian_ZHE }, - { "Armenian_INI", XKB_KEY_Armenian_INI }, - { "Armenian_LYUN", XKB_KEY_Armenian_LYUN }, - { "Armenian_KHE", XKB_KEY_Armenian_KHE }, - { "Armenian_TSA", XKB_KEY_Armenian_TSA }, - { "Armenian_KEN", XKB_KEY_Armenian_KEN }, - { "Armenian_HO", XKB_KEY_Armenian_HO }, - { "Armenian_DZA", XKB_KEY_Armenian_DZA }, - { "Armenian_GHAT", XKB_KEY_Armenian_GHAT }, - { "Armenian_TCHE", XKB_KEY_Armenian_TCHE }, - { "Armenian_MEN", XKB_KEY_Armenian_MEN }, - { "Armenian_HI", XKB_KEY_Armenian_HI }, - { "Armenian_NU", XKB_KEY_Armenian_NU }, - { "Armenian_SHA", XKB_KEY_Armenian_SHA }, - { "Armenian_VO", XKB_KEY_Armenian_VO }, - { "Armenian_CHA", XKB_KEY_Armenian_CHA }, - { "Armenian_PE", XKB_KEY_Armenian_PE }, - { "Armenian_JE", XKB_KEY_Armenian_JE }, - { "Armenian_RA", XKB_KEY_Armenian_RA }, - { "Armenian_SE", XKB_KEY_Armenian_SE }, - { "Armenian_VEV", XKB_KEY_Armenian_VEV }, - { "Armenian_TYUN", XKB_KEY_Armenian_TYUN }, - { "Armenian_RE", XKB_KEY_Armenian_RE }, - { "Armenian_TSO", XKB_KEY_Armenian_TSO }, - { "Armenian_VYUN", XKB_KEY_Armenian_VYUN }, - { "Armenian_PYUR", XKB_KEY_Armenian_PYUR }, - { "Armenian_KE", XKB_KEY_Armenian_KE }, - { "Armenian_O", XKB_KEY_Armenian_O }, - { "Armenian_FE", XKB_KEY_Armenian_FE }, - { "Armenian_apostrophe", XKB_KEY_Armenian_apostrophe }, - { "Armenian_accent", XKB_KEY_Armenian_accent }, - { "Armenian_exclam", XKB_KEY_Armenian_exclam }, - { "Armenian_separation_mark", XKB_KEY_Armenian_separation_mark }, - { "Armenian_question", XKB_KEY_Armenian_question }, - { "Armenian_ayb", XKB_KEY_Armenian_ayb }, - { "Armenian_ben", XKB_KEY_Armenian_ben }, - { "Armenian_gim", XKB_KEY_Armenian_gim }, - { "Armenian_da", XKB_KEY_Armenian_da }, - { "Armenian_yech", XKB_KEY_Armenian_yech }, - { "Armenian_za", XKB_KEY_Armenian_za }, - { "Armenian_e", XKB_KEY_Armenian_e }, - { "Armenian_at", XKB_KEY_Armenian_at }, - { "Armenian_to", XKB_KEY_Armenian_to }, - { "Armenian_zhe", XKB_KEY_Armenian_zhe }, - { "Armenian_ini", XKB_KEY_Armenian_ini }, - { "Armenian_lyun", XKB_KEY_Armenian_lyun }, - { "Armenian_khe", XKB_KEY_Armenian_khe }, - { "Armenian_tsa", XKB_KEY_Armenian_tsa }, - { "Armenian_ken", XKB_KEY_Armenian_ken }, - { "Armenian_ho", XKB_KEY_Armenian_ho }, - { "Armenian_dza", XKB_KEY_Armenian_dza }, - { "Armenian_ghat", XKB_KEY_Armenian_ghat }, - { "Armenian_tche", XKB_KEY_Armenian_tche }, - { "Armenian_men", XKB_KEY_Armenian_men }, - { "Armenian_hi", XKB_KEY_Armenian_hi }, - { "Armenian_nu", XKB_KEY_Armenian_nu }, - { "Armenian_sha", XKB_KEY_Armenian_sha }, - { "Armenian_vo", XKB_KEY_Armenian_vo }, - { "Armenian_cha", XKB_KEY_Armenian_cha }, - { "Armenian_pe", XKB_KEY_Armenian_pe }, - { "Armenian_je", XKB_KEY_Armenian_je }, - { "Armenian_ra", XKB_KEY_Armenian_ra }, - { "Armenian_se", XKB_KEY_Armenian_se }, - { "Armenian_vev", XKB_KEY_Armenian_vev }, - { "Armenian_tyun", XKB_KEY_Armenian_tyun }, - { "Armenian_re", XKB_KEY_Armenian_re }, - { "Armenian_tso", XKB_KEY_Armenian_tso }, - { "Armenian_vyun", XKB_KEY_Armenian_vyun }, - { "Armenian_pyur", XKB_KEY_Armenian_pyur }, - { "Armenian_ke", XKB_KEY_Armenian_ke }, - { "Armenian_o", XKB_KEY_Armenian_o }, - { "Armenian_fe", XKB_KEY_Armenian_fe }, - { "Armenian_ligature_ew", XKB_KEY_Armenian_ligature_ew }, - { "Armenian_full_stop", XKB_KEY_Armenian_full_stop }, - { "Armenian_hyphen", XKB_KEY_Armenian_hyphen }, - { "Arabic_madda_above", XKB_KEY_Arabic_madda_above }, - { "Arabic_hamza_above", XKB_KEY_Arabic_hamza_above }, - { "Arabic_hamza_below", XKB_KEY_Arabic_hamza_below }, - { "Arabic_0", XKB_KEY_Arabic_0 }, - { "Arabic_1", XKB_KEY_Arabic_1 }, - { "Arabic_2", XKB_KEY_Arabic_2 }, - { "Arabic_3", XKB_KEY_Arabic_3 }, - { "Arabic_4", XKB_KEY_Arabic_4 }, - { "Arabic_5", XKB_KEY_Arabic_5 }, - { "Arabic_6", XKB_KEY_Arabic_6 }, - { "Arabic_7", XKB_KEY_Arabic_7 }, - { "Arabic_8", XKB_KEY_Arabic_8 }, - { "Arabic_9", XKB_KEY_Arabic_9 }, - { "Arabic_percent", XKB_KEY_Arabic_percent }, - { "Arabic_superscript_alef", XKB_KEY_Arabic_superscript_alef }, - { "Arabic_tteh", XKB_KEY_Arabic_tteh }, - { "Arabic_peh", XKB_KEY_Arabic_peh }, - { "Arabic_tcheh", XKB_KEY_Arabic_tcheh }, - { "Arabic_ddal", XKB_KEY_Arabic_ddal }, - { "Arabic_rreh", XKB_KEY_Arabic_rreh }, - { "Arabic_jeh", XKB_KEY_Arabic_jeh }, - { "Arabic_veh", XKB_KEY_Arabic_veh }, - { "Arabic_keheh", XKB_KEY_Arabic_keheh }, - { "Arabic_gaf", XKB_KEY_Arabic_gaf }, - { "Arabic_noon_ghunna", XKB_KEY_Arabic_noon_ghunna }, - { "Arabic_heh_doachashmee", XKB_KEY_Arabic_heh_doachashmee }, - { "Arabic_heh_goal", XKB_KEY_Arabic_heh_goal }, - { "Farsi_yeh", XKB_KEY_Farsi_yeh }, - { "Arabic_yeh_baree", XKB_KEY_Arabic_yeh_baree }, - { "Arabic_fullstop", XKB_KEY_Arabic_fullstop }, - { "Farsi_0", XKB_KEY_Farsi_0 }, - { "Farsi_1", XKB_KEY_Farsi_1 }, - { "Farsi_2", XKB_KEY_Farsi_2 }, - { "Farsi_3", XKB_KEY_Farsi_3 }, - { "Farsi_4", XKB_KEY_Farsi_4 }, - { "Farsi_5", XKB_KEY_Farsi_5 }, - { "Farsi_6", XKB_KEY_Farsi_6 }, - { "Farsi_7", XKB_KEY_Farsi_7 }, - { "Farsi_8", XKB_KEY_Farsi_8 }, - { "Farsi_9", XKB_KEY_Farsi_9 }, - { "Sinh_ng", XKB_KEY_Sinh_ng }, - { "Sinh_h2", XKB_KEY_Sinh_h2 }, - { "Sinh_a", XKB_KEY_Sinh_a }, - { "Sinh_aa", XKB_KEY_Sinh_aa }, - { "Sinh_ae", XKB_KEY_Sinh_ae }, - { "Sinh_aee", XKB_KEY_Sinh_aee }, - { "Sinh_i", XKB_KEY_Sinh_i }, - { "Sinh_ii", XKB_KEY_Sinh_ii }, - { "Sinh_u", XKB_KEY_Sinh_u }, - { "Sinh_uu", XKB_KEY_Sinh_uu }, - { "Sinh_ri", XKB_KEY_Sinh_ri }, - { "Sinh_rii", XKB_KEY_Sinh_rii }, - { "Sinh_lu", XKB_KEY_Sinh_lu }, - { "Sinh_luu", XKB_KEY_Sinh_luu }, - { "Sinh_e", XKB_KEY_Sinh_e }, - { "Sinh_ee", XKB_KEY_Sinh_ee }, - { "Sinh_ai", XKB_KEY_Sinh_ai }, - { "Sinh_o", XKB_KEY_Sinh_o }, - { "Sinh_oo", XKB_KEY_Sinh_oo }, - { "Sinh_au", XKB_KEY_Sinh_au }, - { "Sinh_ka", XKB_KEY_Sinh_ka }, - { "Sinh_kha", XKB_KEY_Sinh_kha }, - { "Sinh_ga", XKB_KEY_Sinh_ga }, - { "Sinh_gha", XKB_KEY_Sinh_gha }, - { "Sinh_ng2", XKB_KEY_Sinh_ng2 }, - { "Sinh_nga", XKB_KEY_Sinh_nga }, - { "Sinh_ca", XKB_KEY_Sinh_ca }, - { "Sinh_cha", XKB_KEY_Sinh_cha }, - { "Sinh_ja", XKB_KEY_Sinh_ja }, - { "Sinh_jha", XKB_KEY_Sinh_jha }, - { "Sinh_nya", XKB_KEY_Sinh_nya }, - { "Sinh_jnya", XKB_KEY_Sinh_jnya }, - { "Sinh_nja", XKB_KEY_Sinh_nja }, - { "Sinh_tta", XKB_KEY_Sinh_tta }, - { "Sinh_ttha", XKB_KEY_Sinh_ttha }, - { "Sinh_dda", XKB_KEY_Sinh_dda }, - { "Sinh_ddha", XKB_KEY_Sinh_ddha }, - { "Sinh_nna", XKB_KEY_Sinh_nna }, - { "Sinh_ndda", XKB_KEY_Sinh_ndda }, - { "Sinh_tha", XKB_KEY_Sinh_tha }, - { "Sinh_thha", XKB_KEY_Sinh_thha }, - { "Sinh_dha", XKB_KEY_Sinh_dha }, - { "Sinh_dhha", XKB_KEY_Sinh_dhha }, - { "Sinh_na", XKB_KEY_Sinh_na }, - { "Sinh_ndha", XKB_KEY_Sinh_ndha }, - { "Sinh_pa", XKB_KEY_Sinh_pa }, - { "Sinh_pha", XKB_KEY_Sinh_pha }, - { "Sinh_ba", XKB_KEY_Sinh_ba }, - { "Sinh_bha", XKB_KEY_Sinh_bha }, - { "Sinh_ma", XKB_KEY_Sinh_ma }, - { "Sinh_mba", XKB_KEY_Sinh_mba }, - { "Sinh_ya", XKB_KEY_Sinh_ya }, - { "Sinh_ra", XKB_KEY_Sinh_ra }, - { "Sinh_la", XKB_KEY_Sinh_la }, - { "Sinh_va", XKB_KEY_Sinh_va }, - { "Sinh_sha", XKB_KEY_Sinh_sha }, - { "Sinh_ssha", XKB_KEY_Sinh_ssha }, - { "Sinh_sa", XKB_KEY_Sinh_sa }, - { "Sinh_ha", XKB_KEY_Sinh_ha }, - { "Sinh_lla", XKB_KEY_Sinh_lla }, - { "Sinh_fa", XKB_KEY_Sinh_fa }, - { "Sinh_al", XKB_KEY_Sinh_al }, - { "Sinh_aa2", XKB_KEY_Sinh_aa2 }, - { "Sinh_ae2", XKB_KEY_Sinh_ae2 }, - { "Sinh_aee2", XKB_KEY_Sinh_aee2 }, - { "Sinh_i2", XKB_KEY_Sinh_i2 }, - { "Sinh_ii2", XKB_KEY_Sinh_ii2 }, - { "Sinh_u2", XKB_KEY_Sinh_u2 }, - { "Sinh_uu2", XKB_KEY_Sinh_uu2 }, - { "Sinh_ru2", XKB_KEY_Sinh_ru2 }, - { "Sinh_e2", XKB_KEY_Sinh_e2 }, - { "Sinh_ee2", XKB_KEY_Sinh_ee2 }, - { "Sinh_ai2", XKB_KEY_Sinh_ai2 }, - { "Sinh_o2", XKB_KEY_Sinh_o2 }, - { "Sinh_oo2", XKB_KEY_Sinh_oo2 }, - { "Sinh_au2", XKB_KEY_Sinh_au2 }, - { "Sinh_lu2", XKB_KEY_Sinh_lu2 }, - { "Sinh_ruu2", XKB_KEY_Sinh_ruu2 }, - { "Sinh_luu2", XKB_KEY_Sinh_luu2 }, - { "Sinh_kunddaliya", XKB_KEY_Sinh_kunddaliya }, - { "Georgian_an", XKB_KEY_Georgian_an }, - { "Georgian_ban", XKB_KEY_Georgian_ban }, - { "Georgian_gan", XKB_KEY_Georgian_gan }, - { "Georgian_don", XKB_KEY_Georgian_don }, - { "Georgian_en", XKB_KEY_Georgian_en }, - { "Georgian_vin", XKB_KEY_Georgian_vin }, - { "Georgian_zen", XKB_KEY_Georgian_zen }, - { "Georgian_tan", XKB_KEY_Georgian_tan }, - { "Georgian_in", XKB_KEY_Georgian_in }, - { "Georgian_kan", XKB_KEY_Georgian_kan }, - { "Georgian_las", XKB_KEY_Georgian_las }, - { "Georgian_man", XKB_KEY_Georgian_man }, - { "Georgian_nar", XKB_KEY_Georgian_nar }, - { "Georgian_on", XKB_KEY_Georgian_on }, - { "Georgian_par", XKB_KEY_Georgian_par }, - { "Georgian_zhar", XKB_KEY_Georgian_zhar }, - { "Georgian_rae", XKB_KEY_Georgian_rae }, - { "Georgian_san", XKB_KEY_Georgian_san }, - { "Georgian_tar", XKB_KEY_Georgian_tar }, - { "Georgian_un", XKB_KEY_Georgian_un }, - { "Georgian_phar", XKB_KEY_Georgian_phar }, - { "Georgian_khar", XKB_KEY_Georgian_khar }, - { "Georgian_ghan", XKB_KEY_Georgian_ghan }, - { "Georgian_qar", XKB_KEY_Georgian_qar }, - { "Georgian_shin", XKB_KEY_Georgian_shin }, - { "Georgian_chin", XKB_KEY_Georgian_chin }, - { "Georgian_can", XKB_KEY_Georgian_can }, - { "Georgian_jil", XKB_KEY_Georgian_jil }, - { "Georgian_cil", XKB_KEY_Georgian_cil }, - { "Georgian_char", XKB_KEY_Georgian_char }, - { "Georgian_xan", XKB_KEY_Georgian_xan }, - { "Georgian_jhan", XKB_KEY_Georgian_jhan }, - { "Georgian_hae", XKB_KEY_Georgian_hae }, - { "Georgian_he", XKB_KEY_Georgian_he }, - { "Georgian_hie", XKB_KEY_Georgian_hie }, - { "Georgian_we", XKB_KEY_Georgian_we }, - { "Georgian_har", XKB_KEY_Georgian_har }, - { "Georgian_hoe", XKB_KEY_Georgian_hoe }, - { "Georgian_fi", XKB_KEY_Georgian_fi }, - { "Babovedot", XKB_KEY_Babovedot }, - { "babovedot", XKB_KEY_babovedot }, - { "Dabovedot", XKB_KEY_Dabovedot }, - { "dabovedot", XKB_KEY_dabovedot }, - { "Fabovedot", XKB_KEY_Fabovedot }, - { "fabovedot", XKB_KEY_fabovedot }, - { "Lbelowdot", XKB_KEY_Lbelowdot }, - { "lbelowdot", XKB_KEY_lbelowdot }, - { "Mabovedot", XKB_KEY_Mabovedot }, - { "mabovedot", XKB_KEY_mabovedot }, - { "Pabovedot", XKB_KEY_Pabovedot }, - { "pabovedot", XKB_KEY_pabovedot }, - { "Sabovedot", XKB_KEY_Sabovedot }, - { "sabovedot", XKB_KEY_sabovedot }, - { "Tabovedot", XKB_KEY_Tabovedot }, - { "tabovedot", XKB_KEY_tabovedot }, - { "Wgrave", XKB_KEY_Wgrave }, - { "wgrave", XKB_KEY_wgrave }, - { "Wacute", XKB_KEY_Wacute }, - { "wacute", XKB_KEY_wacute }, - { "Wdiaeresis", XKB_KEY_Wdiaeresis }, - { "wdiaeresis", XKB_KEY_wdiaeresis }, - { "Xabovedot", XKB_KEY_Xabovedot }, - { "xabovedot", XKB_KEY_xabovedot }, - { "Abelowdot", XKB_KEY_Abelowdot }, - { "abelowdot", XKB_KEY_abelowdot }, - { "Ahook", XKB_KEY_Ahook }, - { "ahook", XKB_KEY_ahook }, - { "Acircumflexacute", XKB_KEY_Acircumflexacute }, - { "acircumflexacute", XKB_KEY_acircumflexacute }, - { "Acircumflexgrave", XKB_KEY_Acircumflexgrave }, - { "acircumflexgrave", XKB_KEY_acircumflexgrave }, - { "Acircumflexhook", XKB_KEY_Acircumflexhook }, - { "acircumflexhook", XKB_KEY_acircumflexhook }, - { "Acircumflextilde", XKB_KEY_Acircumflextilde }, - { "acircumflextilde", XKB_KEY_acircumflextilde }, - { "Acircumflexbelowdot", XKB_KEY_Acircumflexbelowdot }, - { "acircumflexbelowdot", XKB_KEY_acircumflexbelowdot }, - { "Abreveacute", XKB_KEY_Abreveacute }, - { "abreveacute", XKB_KEY_abreveacute }, - { "Abrevegrave", XKB_KEY_Abrevegrave }, - { "abrevegrave", XKB_KEY_abrevegrave }, - { "Abrevehook", XKB_KEY_Abrevehook }, - { "abrevehook", XKB_KEY_abrevehook }, - { "Abrevetilde", XKB_KEY_Abrevetilde }, - { "abrevetilde", XKB_KEY_abrevetilde }, - { "Abrevebelowdot", XKB_KEY_Abrevebelowdot }, - { "abrevebelowdot", XKB_KEY_abrevebelowdot }, - { "Ebelowdot", XKB_KEY_Ebelowdot }, - { "ebelowdot", XKB_KEY_ebelowdot }, - { "Ehook", XKB_KEY_Ehook }, - { "ehook", XKB_KEY_ehook }, - { "Etilde", XKB_KEY_Etilde }, - { "etilde", XKB_KEY_etilde }, - { "Ecircumflexacute", XKB_KEY_Ecircumflexacute }, - { "ecircumflexacute", XKB_KEY_ecircumflexacute }, - { "Ecircumflexgrave", XKB_KEY_Ecircumflexgrave }, - { "ecircumflexgrave", XKB_KEY_ecircumflexgrave }, - { "Ecircumflexhook", XKB_KEY_Ecircumflexhook }, - { "ecircumflexhook", XKB_KEY_ecircumflexhook }, - { "Ecircumflextilde", XKB_KEY_Ecircumflextilde }, - { "ecircumflextilde", XKB_KEY_ecircumflextilde }, - { "Ecircumflexbelowdot", XKB_KEY_Ecircumflexbelowdot }, - { "ecircumflexbelowdot", XKB_KEY_ecircumflexbelowdot }, - { "Ihook", XKB_KEY_Ihook }, - { "ihook", XKB_KEY_ihook }, - { "Ibelowdot", XKB_KEY_Ibelowdot }, - { "ibelowdot", XKB_KEY_ibelowdot }, - { "Obelowdot", XKB_KEY_Obelowdot }, - { "obelowdot", XKB_KEY_obelowdot }, - { "Ohook", XKB_KEY_Ohook }, - { "ohook", XKB_KEY_ohook }, - { "Ocircumflexacute", XKB_KEY_Ocircumflexacute }, - { "ocircumflexacute", XKB_KEY_ocircumflexacute }, - { "Ocircumflexgrave", XKB_KEY_Ocircumflexgrave }, - { "ocircumflexgrave", XKB_KEY_ocircumflexgrave }, - { "Ocircumflexhook", XKB_KEY_Ocircumflexhook }, - { "ocircumflexhook", XKB_KEY_ocircumflexhook }, - { "Ocircumflextilde", XKB_KEY_Ocircumflextilde }, - { "ocircumflextilde", XKB_KEY_ocircumflextilde }, - { "Ocircumflexbelowdot", XKB_KEY_Ocircumflexbelowdot }, - { "ocircumflexbelowdot", XKB_KEY_ocircumflexbelowdot }, - { "Ohornacute", XKB_KEY_Ohornacute }, - { "ohornacute", XKB_KEY_ohornacute }, - { "Ohorngrave", XKB_KEY_Ohorngrave }, - { "ohorngrave", XKB_KEY_ohorngrave }, - { "Ohornhook", XKB_KEY_Ohornhook }, - { "ohornhook", XKB_KEY_ohornhook }, - { "Ohorntilde", XKB_KEY_Ohorntilde }, - { "ohorntilde", XKB_KEY_ohorntilde }, - { "Ohornbelowdot", XKB_KEY_Ohornbelowdot }, - { "ohornbelowdot", XKB_KEY_ohornbelowdot }, - { "Ubelowdot", XKB_KEY_Ubelowdot }, - { "ubelowdot", XKB_KEY_ubelowdot }, - { "Uhook", XKB_KEY_Uhook }, - { "uhook", XKB_KEY_uhook }, - { "Uhornacute", XKB_KEY_Uhornacute }, - { "uhornacute", XKB_KEY_uhornacute }, - { "Uhorngrave", XKB_KEY_Uhorngrave }, - { "uhorngrave", XKB_KEY_uhorngrave }, - { "Uhornhook", XKB_KEY_Uhornhook }, - { "uhornhook", XKB_KEY_uhornhook }, - { "Uhorntilde", XKB_KEY_Uhorntilde }, - { "uhorntilde", XKB_KEY_uhorntilde }, - { "Uhornbelowdot", XKB_KEY_Uhornbelowdot }, - { "uhornbelowdot", XKB_KEY_uhornbelowdot }, - { "Ygrave", XKB_KEY_Ygrave }, - { "ygrave", XKB_KEY_ygrave }, - { "Ybelowdot", XKB_KEY_Ybelowdot }, - { "ybelowdot", XKB_KEY_ybelowdot }, - { "Yhook", XKB_KEY_Yhook }, - { "yhook", XKB_KEY_yhook }, - { "Ytilde", XKB_KEY_Ytilde }, - { "ytilde", XKB_KEY_ytilde }, - { "zerosuperior", XKB_KEY_zerosuperior }, - { "foursuperior", XKB_KEY_foursuperior }, - { "fivesuperior", XKB_KEY_fivesuperior }, - { "sixsuperior", XKB_KEY_sixsuperior }, - { "sevensuperior", XKB_KEY_sevensuperior }, - { "eightsuperior", XKB_KEY_eightsuperior }, - { "ninesuperior", XKB_KEY_ninesuperior }, - { "zerosubscript", XKB_KEY_zerosubscript }, - { "onesubscript", XKB_KEY_onesubscript }, - { "twosubscript", XKB_KEY_twosubscript }, - { "threesubscript", XKB_KEY_threesubscript }, - { "foursubscript", XKB_KEY_foursubscript }, - { "fivesubscript", XKB_KEY_fivesubscript }, - { "sixsubscript", XKB_KEY_sixsubscript }, - { "sevensubscript", XKB_KEY_sevensubscript }, - { "eightsubscript", XKB_KEY_eightsubscript }, - { "ninesubscript", XKB_KEY_ninesubscript }, - { "EcuSign", XKB_KEY_EcuSign }, - { "ColonSign", XKB_KEY_ColonSign }, - { "CruzeiroSign", XKB_KEY_CruzeiroSign }, - { "FFrancSign", XKB_KEY_FFrancSign }, - { "LiraSign", XKB_KEY_LiraSign }, - { "MillSign", XKB_KEY_MillSign }, - { "NairaSign", XKB_KEY_NairaSign }, - { "PesetaSign", XKB_KEY_PesetaSign }, - { "RupeeSign", XKB_KEY_RupeeSign }, - { "WonSign", XKB_KEY_WonSign }, - { "NewSheqelSign", XKB_KEY_NewSheqelSign }, - { "DongSign", XKB_KEY_DongSign }, - { "partdifferential", XKB_KEY_partdifferential }, - { "emptyset", XKB_KEY_emptyset }, - { "elementof", XKB_KEY_elementof }, - { "notelementof", XKB_KEY_notelementof }, - { "containsas", XKB_KEY_containsas }, - { "squareroot", XKB_KEY_squareroot }, - { "cuberoot", XKB_KEY_cuberoot }, - { "fourthroot", XKB_KEY_fourthroot }, - { "dintegral", XKB_KEY_dintegral }, - { "tintegral", XKB_KEY_tintegral }, - { "because", XKB_KEY_because }, - { "notapproxeq", XKB_KEY_notapproxeq }, - { "approxeq", XKB_KEY_approxeq }, - { "notidentical", XKB_KEY_notidentical }, - { "stricteq", XKB_KEY_stricteq }, - { "braille_blank", XKB_KEY_braille_blank }, - { "braille_dots_1", XKB_KEY_braille_dots_1 }, - { "braille_dots_2", XKB_KEY_braille_dots_2 }, - { "braille_dots_12", XKB_KEY_braille_dots_12 }, - { "braille_dots_3", XKB_KEY_braille_dots_3 }, - { "braille_dots_13", XKB_KEY_braille_dots_13 }, - { "braille_dots_23", XKB_KEY_braille_dots_23 }, - { "braille_dots_123", XKB_KEY_braille_dots_123 }, - { "braille_dots_4", XKB_KEY_braille_dots_4 }, - { "braille_dots_14", XKB_KEY_braille_dots_14 }, - { "braille_dots_24", XKB_KEY_braille_dots_24 }, - { "braille_dots_124", XKB_KEY_braille_dots_124 }, - { "braille_dots_34", XKB_KEY_braille_dots_34 }, - { "braille_dots_134", XKB_KEY_braille_dots_134 }, - { "braille_dots_234", XKB_KEY_braille_dots_234 }, - { "braille_dots_1234", XKB_KEY_braille_dots_1234 }, - { "braille_dots_5", XKB_KEY_braille_dots_5 }, - { "braille_dots_15", XKB_KEY_braille_dots_15 }, - { "braille_dots_25", XKB_KEY_braille_dots_25 }, - { "braille_dots_125", XKB_KEY_braille_dots_125 }, - { "braille_dots_35", XKB_KEY_braille_dots_35 }, - { "braille_dots_135", XKB_KEY_braille_dots_135 }, - { "braille_dots_235", XKB_KEY_braille_dots_235 }, - { "braille_dots_1235", XKB_KEY_braille_dots_1235 }, - { "braille_dots_45", XKB_KEY_braille_dots_45 }, - { "braille_dots_145", XKB_KEY_braille_dots_145 }, - { "braille_dots_245", XKB_KEY_braille_dots_245 }, - { "braille_dots_1245", XKB_KEY_braille_dots_1245 }, - { "braille_dots_345", XKB_KEY_braille_dots_345 }, - { "braille_dots_1345", XKB_KEY_braille_dots_1345 }, - { "braille_dots_2345", XKB_KEY_braille_dots_2345 }, - { "braille_dots_12345", XKB_KEY_braille_dots_12345 }, - { "braille_dots_6", XKB_KEY_braille_dots_6 }, - { "braille_dots_16", XKB_KEY_braille_dots_16 }, - { "braille_dots_26", XKB_KEY_braille_dots_26 }, - { "braille_dots_126", XKB_KEY_braille_dots_126 }, - { "braille_dots_36", XKB_KEY_braille_dots_36 }, - { "braille_dots_136", XKB_KEY_braille_dots_136 }, - { "braille_dots_236", XKB_KEY_braille_dots_236 }, - { "braille_dots_1236", XKB_KEY_braille_dots_1236 }, - { "braille_dots_46", XKB_KEY_braille_dots_46 }, - { "braille_dots_146", XKB_KEY_braille_dots_146 }, - { "braille_dots_246", XKB_KEY_braille_dots_246 }, - { "braille_dots_1246", XKB_KEY_braille_dots_1246 }, - { "braille_dots_346", XKB_KEY_braille_dots_346 }, - { "braille_dots_1346", XKB_KEY_braille_dots_1346 }, - { "braille_dots_2346", XKB_KEY_braille_dots_2346 }, - { "braille_dots_12346", XKB_KEY_braille_dots_12346 }, - { "braille_dots_56", XKB_KEY_braille_dots_56 }, - { "braille_dots_156", XKB_KEY_braille_dots_156 }, - { "braille_dots_256", XKB_KEY_braille_dots_256 }, - { "braille_dots_1256", XKB_KEY_braille_dots_1256 }, - { "braille_dots_356", XKB_KEY_braille_dots_356 }, - { "braille_dots_1356", XKB_KEY_braille_dots_1356 }, - { "braille_dots_2356", XKB_KEY_braille_dots_2356 }, - { "braille_dots_12356", XKB_KEY_braille_dots_12356 }, - { "braille_dots_456", XKB_KEY_braille_dots_456 }, - { "braille_dots_1456", XKB_KEY_braille_dots_1456 }, - { "braille_dots_2456", XKB_KEY_braille_dots_2456 }, - { "braille_dots_12456", XKB_KEY_braille_dots_12456 }, - { "braille_dots_3456", XKB_KEY_braille_dots_3456 }, - { "braille_dots_13456", XKB_KEY_braille_dots_13456 }, - { "braille_dots_23456", XKB_KEY_braille_dots_23456 }, - { "braille_dots_123456", XKB_KEY_braille_dots_123456 }, - { "braille_dots_7", XKB_KEY_braille_dots_7 }, - { "braille_dots_17", XKB_KEY_braille_dots_17 }, - { "braille_dots_27", XKB_KEY_braille_dots_27 }, - { "braille_dots_127", XKB_KEY_braille_dots_127 }, - { "braille_dots_37", XKB_KEY_braille_dots_37 }, - { "braille_dots_137", XKB_KEY_braille_dots_137 }, - { "braille_dots_237", XKB_KEY_braille_dots_237 }, - { "braille_dots_1237", XKB_KEY_braille_dots_1237 }, - { "braille_dots_47", XKB_KEY_braille_dots_47 }, - { "braille_dots_147", XKB_KEY_braille_dots_147 }, - { "braille_dots_247", XKB_KEY_braille_dots_247 }, - { "braille_dots_1247", XKB_KEY_braille_dots_1247 }, - { "braille_dots_347", XKB_KEY_braille_dots_347 }, - { "braille_dots_1347", XKB_KEY_braille_dots_1347 }, - { "braille_dots_2347", XKB_KEY_braille_dots_2347 }, - { "braille_dots_12347", XKB_KEY_braille_dots_12347 }, - { "braille_dots_57", XKB_KEY_braille_dots_57 }, - { "braille_dots_157", XKB_KEY_braille_dots_157 }, - { "braille_dots_257", XKB_KEY_braille_dots_257 }, - { "braille_dots_1257", XKB_KEY_braille_dots_1257 }, - { "braille_dots_357", XKB_KEY_braille_dots_357 }, - { "braille_dots_1357", XKB_KEY_braille_dots_1357 }, - { "braille_dots_2357", XKB_KEY_braille_dots_2357 }, - { "braille_dots_12357", XKB_KEY_braille_dots_12357 }, - { "braille_dots_457", XKB_KEY_braille_dots_457 }, - { "braille_dots_1457", XKB_KEY_braille_dots_1457 }, - { "braille_dots_2457", XKB_KEY_braille_dots_2457 }, - { "braille_dots_12457", XKB_KEY_braille_dots_12457 }, - { "braille_dots_3457", XKB_KEY_braille_dots_3457 }, - { "braille_dots_13457", XKB_KEY_braille_dots_13457 }, - { "braille_dots_23457", XKB_KEY_braille_dots_23457 }, - { "braille_dots_123457", XKB_KEY_braille_dots_123457 }, - { "braille_dots_67", XKB_KEY_braille_dots_67 }, - { "braille_dots_167", XKB_KEY_braille_dots_167 }, - { "braille_dots_267", XKB_KEY_braille_dots_267 }, - { "braille_dots_1267", XKB_KEY_braille_dots_1267 }, - { "braille_dots_367", XKB_KEY_braille_dots_367 }, - { "braille_dots_1367", XKB_KEY_braille_dots_1367 }, - { "braille_dots_2367", XKB_KEY_braille_dots_2367 }, - { "braille_dots_12367", XKB_KEY_braille_dots_12367 }, - { "braille_dots_467", XKB_KEY_braille_dots_467 }, - { "braille_dots_1467", XKB_KEY_braille_dots_1467 }, - { "braille_dots_2467", XKB_KEY_braille_dots_2467 }, - { "braille_dots_12467", XKB_KEY_braille_dots_12467 }, - { "braille_dots_3467", XKB_KEY_braille_dots_3467 }, - { "braille_dots_13467", XKB_KEY_braille_dots_13467 }, - { "braille_dots_23467", XKB_KEY_braille_dots_23467 }, - { "braille_dots_123467", XKB_KEY_braille_dots_123467 }, - { "braille_dots_567", XKB_KEY_braille_dots_567 }, - { "braille_dots_1567", XKB_KEY_braille_dots_1567 }, - { "braille_dots_2567", XKB_KEY_braille_dots_2567 }, - { "braille_dots_12567", XKB_KEY_braille_dots_12567 }, - { "braille_dots_3567", XKB_KEY_braille_dots_3567 }, - { "braille_dots_13567", XKB_KEY_braille_dots_13567 }, - { "braille_dots_23567", XKB_KEY_braille_dots_23567 }, - { "braille_dots_123567", XKB_KEY_braille_dots_123567 }, - { "braille_dots_4567", XKB_KEY_braille_dots_4567 }, - { "braille_dots_14567", XKB_KEY_braille_dots_14567 }, - { "braille_dots_24567", XKB_KEY_braille_dots_24567 }, - { "braille_dots_124567", XKB_KEY_braille_dots_124567 }, - { "braille_dots_34567", XKB_KEY_braille_dots_34567 }, - { "braille_dots_134567", XKB_KEY_braille_dots_134567 }, - { "braille_dots_234567", XKB_KEY_braille_dots_234567 }, - { "braille_dots_1234567", XKB_KEY_braille_dots_1234567 }, - { "braille_dots_8", XKB_KEY_braille_dots_8 }, - { "braille_dots_18", XKB_KEY_braille_dots_18 }, - { "braille_dots_28", XKB_KEY_braille_dots_28 }, - { "braille_dots_128", XKB_KEY_braille_dots_128 }, - { "braille_dots_38", XKB_KEY_braille_dots_38 }, - { "braille_dots_138", XKB_KEY_braille_dots_138 }, - { "braille_dots_238", XKB_KEY_braille_dots_238 }, - { "braille_dots_1238", XKB_KEY_braille_dots_1238 }, - { "braille_dots_48", XKB_KEY_braille_dots_48 }, - { "braille_dots_148", XKB_KEY_braille_dots_148 }, - { "braille_dots_248", XKB_KEY_braille_dots_248 }, - { "braille_dots_1248", XKB_KEY_braille_dots_1248 }, - { "braille_dots_348", XKB_KEY_braille_dots_348 }, - { "braille_dots_1348", XKB_KEY_braille_dots_1348 }, - { "braille_dots_2348", XKB_KEY_braille_dots_2348 }, - { "braille_dots_12348", XKB_KEY_braille_dots_12348 }, - { "braille_dots_58", XKB_KEY_braille_dots_58 }, - { "braille_dots_158", XKB_KEY_braille_dots_158 }, - { "braille_dots_258", XKB_KEY_braille_dots_258 }, - { "braille_dots_1258", XKB_KEY_braille_dots_1258 }, - { "braille_dots_358", XKB_KEY_braille_dots_358 }, - { "braille_dots_1358", XKB_KEY_braille_dots_1358 }, - { "braille_dots_2358", XKB_KEY_braille_dots_2358 }, - { "braille_dots_12358", XKB_KEY_braille_dots_12358 }, - { "braille_dots_458", XKB_KEY_braille_dots_458 }, - { "braille_dots_1458", XKB_KEY_braille_dots_1458 }, - { "braille_dots_2458", XKB_KEY_braille_dots_2458 }, - { "braille_dots_12458", XKB_KEY_braille_dots_12458 }, - { "braille_dots_3458", XKB_KEY_braille_dots_3458 }, - { "braille_dots_13458", XKB_KEY_braille_dots_13458 }, - { "braille_dots_23458", XKB_KEY_braille_dots_23458 }, - { "braille_dots_123458", XKB_KEY_braille_dots_123458 }, - { "braille_dots_68", XKB_KEY_braille_dots_68 }, - { "braille_dots_168", XKB_KEY_braille_dots_168 }, - { "braille_dots_268", XKB_KEY_braille_dots_268 }, - { "braille_dots_1268", XKB_KEY_braille_dots_1268 }, - { "braille_dots_368", XKB_KEY_braille_dots_368 }, - { "braille_dots_1368", XKB_KEY_braille_dots_1368 }, - { "braille_dots_2368", XKB_KEY_braille_dots_2368 }, - { "braille_dots_12368", XKB_KEY_braille_dots_12368 }, - { "braille_dots_468", XKB_KEY_braille_dots_468 }, - { "braille_dots_1468", XKB_KEY_braille_dots_1468 }, - { "braille_dots_2468", XKB_KEY_braille_dots_2468 }, - { "braille_dots_12468", XKB_KEY_braille_dots_12468 }, - { "braille_dots_3468", XKB_KEY_braille_dots_3468 }, - { "braille_dots_13468", XKB_KEY_braille_dots_13468 }, - { "braille_dots_23468", XKB_KEY_braille_dots_23468 }, - { "braille_dots_123468", XKB_KEY_braille_dots_123468 }, - { "braille_dots_568", XKB_KEY_braille_dots_568 }, - { "braille_dots_1568", XKB_KEY_braille_dots_1568 }, - { "braille_dots_2568", XKB_KEY_braille_dots_2568 }, - { "braille_dots_12568", XKB_KEY_braille_dots_12568 }, - { "braille_dots_3568", XKB_KEY_braille_dots_3568 }, - { "braille_dots_13568", XKB_KEY_braille_dots_13568 }, - { "braille_dots_23568", XKB_KEY_braille_dots_23568 }, - { "braille_dots_123568", XKB_KEY_braille_dots_123568 }, - { "braille_dots_4568", XKB_KEY_braille_dots_4568 }, - { "braille_dots_14568", XKB_KEY_braille_dots_14568 }, - { "braille_dots_24568", XKB_KEY_braille_dots_24568 }, - { "braille_dots_124568", XKB_KEY_braille_dots_124568 }, - { "braille_dots_34568", XKB_KEY_braille_dots_34568 }, - { "braille_dots_134568", XKB_KEY_braille_dots_134568 }, - { "braille_dots_234568", XKB_KEY_braille_dots_234568 }, - { "braille_dots_1234568", XKB_KEY_braille_dots_1234568 }, - { "braille_dots_78", XKB_KEY_braille_dots_78 }, - { "braille_dots_178", XKB_KEY_braille_dots_178 }, - { "braille_dots_278", XKB_KEY_braille_dots_278 }, - { "braille_dots_1278", XKB_KEY_braille_dots_1278 }, - { "braille_dots_378", XKB_KEY_braille_dots_378 }, - { "braille_dots_1378", XKB_KEY_braille_dots_1378 }, - { "braille_dots_2378", XKB_KEY_braille_dots_2378 }, - { "braille_dots_12378", XKB_KEY_braille_dots_12378 }, - { "braille_dots_478", XKB_KEY_braille_dots_478 }, - { "braille_dots_1478", XKB_KEY_braille_dots_1478 }, - { "braille_dots_2478", XKB_KEY_braille_dots_2478 }, - { "braille_dots_12478", XKB_KEY_braille_dots_12478 }, - { "braille_dots_3478", XKB_KEY_braille_dots_3478 }, - { "braille_dots_13478", XKB_KEY_braille_dots_13478 }, - { "braille_dots_23478", XKB_KEY_braille_dots_23478 }, - { "braille_dots_123478", XKB_KEY_braille_dots_123478 }, - { "braille_dots_578", XKB_KEY_braille_dots_578 }, - { "braille_dots_1578", XKB_KEY_braille_dots_1578 }, - { "braille_dots_2578", XKB_KEY_braille_dots_2578 }, - { "braille_dots_12578", XKB_KEY_braille_dots_12578 }, - { "braille_dots_3578", XKB_KEY_braille_dots_3578 }, - { "braille_dots_13578", XKB_KEY_braille_dots_13578 }, - { "braille_dots_23578", XKB_KEY_braille_dots_23578 }, - { "braille_dots_123578", XKB_KEY_braille_dots_123578 }, - { "braille_dots_4578", XKB_KEY_braille_dots_4578 }, - { "braille_dots_14578", XKB_KEY_braille_dots_14578 }, - { "braille_dots_24578", XKB_KEY_braille_dots_24578 }, - { "braille_dots_124578", XKB_KEY_braille_dots_124578 }, - { "braille_dots_34578", XKB_KEY_braille_dots_34578 }, - { "braille_dots_134578", XKB_KEY_braille_dots_134578 }, - { "braille_dots_234578", XKB_KEY_braille_dots_234578 }, - { "braille_dots_1234578", XKB_KEY_braille_dots_1234578 }, - { "braille_dots_678", XKB_KEY_braille_dots_678 }, - { "braille_dots_1678", XKB_KEY_braille_dots_1678 }, - { "braille_dots_2678", XKB_KEY_braille_dots_2678 }, - { "braille_dots_12678", XKB_KEY_braille_dots_12678 }, - { "braille_dots_3678", XKB_KEY_braille_dots_3678 }, - { "braille_dots_13678", XKB_KEY_braille_dots_13678 }, - { "braille_dots_23678", XKB_KEY_braille_dots_23678 }, - { "braille_dots_123678", XKB_KEY_braille_dots_123678 }, - { "braille_dots_4678", XKB_KEY_braille_dots_4678 }, - { "braille_dots_14678", XKB_KEY_braille_dots_14678 }, - { "braille_dots_24678", XKB_KEY_braille_dots_24678 }, - { "braille_dots_124678", XKB_KEY_braille_dots_124678 }, - { "braille_dots_34678", XKB_KEY_braille_dots_34678 }, - { "braille_dots_134678", XKB_KEY_braille_dots_134678 }, - { "braille_dots_234678", XKB_KEY_braille_dots_234678 }, - { "braille_dots_1234678", XKB_KEY_braille_dots_1234678 }, - { "braille_dots_5678", XKB_KEY_braille_dots_5678 }, - { "braille_dots_15678", XKB_KEY_braille_dots_15678 }, - { "braille_dots_25678", XKB_KEY_braille_dots_25678 }, - { "braille_dots_125678", XKB_KEY_braille_dots_125678 }, - { "braille_dots_35678", XKB_KEY_braille_dots_35678 }, - { "braille_dots_135678", XKB_KEY_braille_dots_135678 }, - { "braille_dots_235678", XKB_KEY_braille_dots_235678 }, - { "braille_dots_1235678", XKB_KEY_braille_dots_1235678 }, - { "braille_dots_45678", XKB_KEY_braille_dots_45678 }, - { "braille_dots_145678", XKB_KEY_braille_dots_145678 }, - { "braille_dots_245678", XKB_KEY_braille_dots_245678 }, - { "braille_dots_1245678", XKB_KEY_braille_dots_1245678 }, - { "braille_dots_345678", XKB_KEY_braille_dots_345678 }, - { "braille_dots_1345678", XKB_KEY_braille_dots_1345678 }, - { "braille_dots_2345678", XKB_KEY_braille_dots_2345678 }, - { "braille_dots_12345678", XKB_KEY_braille_dots_12345678 }, - { "hpmute_acute", XKB_KEY_hpmute_acute }, - { "hpmute_grave", XKB_KEY_hpmute_grave }, - { "hpmute_asciicircum", XKB_KEY_hpmute_asciicircum }, - { "hpmute_diaeresis", XKB_KEY_hpmute_diaeresis }, - { "hpmute_asciitilde", XKB_KEY_hpmute_asciitilde }, - { "hplira", XKB_KEY_hplira }, - { "hpguilder", XKB_KEY_hpguilder }, - { "hpYdiaeresis", XKB_KEY_hpYdiaeresis }, - { "hplongminus", XKB_KEY_hplongminus }, - { "hpblock", XKB_KEY_hpblock }, - { "Ddiaeresis", XKB_KEY_Ddiaeresis }, - { "Dacute_accent", XKB_KEY_Dacute_accent }, - { "Dcedilla_accent", XKB_KEY_Dcedilla_accent }, - { "Dcircumflex_accent", XKB_KEY_Dcircumflex_accent }, - { "Dgrave_accent", XKB_KEY_Dgrave_accent }, - { "Dtilde", XKB_KEY_Dtilde }, - { "Dring_accent", XKB_KEY_Dring_accent }, - { "DRemove", XKB_KEY_DRemove }, - { "hpModelock1", XKB_KEY_hpModelock1 }, - { "hpModelock2", XKB_KEY_hpModelock2 }, - { "hpReset", XKB_KEY_hpReset }, - { "hpSystem", XKB_KEY_hpSystem }, - { "hpUser", XKB_KEY_hpUser }, - { "hpClearLine", XKB_KEY_hpClearLine }, - { "hpInsertLine", XKB_KEY_hpInsertLine }, - { "hpDeleteLine", XKB_KEY_hpDeleteLine }, - { "hpInsertChar", XKB_KEY_hpInsertChar }, - { "hpDeleteChar", XKB_KEY_hpDeleteChar }, - { "hpBackTab", XKB_KEY_hpBackTab }, - { "hpKP_BackTab", XKB_KEY_hpKP_BackTab }, - { "Ext16bit_L", XKB_KEY_Ext16bit_L }, - { "Ext16bit_R", XKB_KEY_Ext16bit_R }, - { "osfCopy", XKB_KEY_osfCopy }, - { "osfCut", XKB_KEY_osfCut }, - { "osfPaste", XKB_KEY_osfPaste }, - { "osfBackTab", XKB_KEY_osfBackTab }, - { "osfBackSpace", XKB_KEY_osfBackSpace }, - { "osfClear", XKB_KEY_osfClear }, - { "osfEscape", XKB_KEY_osfEscape }, - { "osfAddMode", XKB_KEY_osfAddMode }, - { "osfPrimaryPaste", XKB_KEY_osfPrimaryPaste }, - { "osfQuickPaste", XKB_KEY_osfQuickPaste }, - { "osfPageLeft", XKB_KEY_osfPageLeft }, - { "osfPageUp", XKB_KEY_osfPageUp }, - { "osfPageDown", XKB_KEY_osfPageDown }, - { "osfPageRight", XKB_KEY_osfPageRight }, - { "osfActivate", XKB_KEY_osfActivate }, - { "osfMenuBar", XKB_KEY_osfMenuBar }, - { "osfLeft", XKB_KEY_osfLeft }, - { "osfUp", XKB_KEY_osfUp }, - { "osfRight", XKB_KEY_osfRight }, - { "osfDown", XKB_KEY_osfDown }, - { "osfEndLine", XKB_KEY_osfEndLine }, - { "osfBeginLine", XKB_KEY_osfBeginLine }, - { "osfEndData", XKB_KEY_osfEndData }, - { "osfBeginData", XKB_KEY_osfBeginData }, - { "osfPrevMenu", XKB_KEY_osfPrevMenu }, - { "osfNextMenu", XKB_KEY_osfNextMenu }, - { "osfPrevField", XKB_KEY_osfPrevField }, - { "osfNextField", XKB_KEY_osfNextField }, - { "osfSelect", XKB_KEY_osfSelect }, - { "osfInsert", XKB_KEY_osfInsert }, - { "osfUndo", XKB_KEY_osfUndo }, - { "osfMenu", XKB_KEY_osfMenu }, - { "osfCancel", XKB_KEY_osfCancel }, - { "osfHelp", XKB_KEY_osfHelp }, - { "osfSelectAll", XKB_KEY_osfSelectAll }, - { "osfDeselectAll", XKB_KEY_osfDeselectAll }, - { "osfReselect", XKB_KEY_osfReselect }, - { "osfExtend", XKB_KEY_osfExtend }, - { "osfRestore", XKB_KEY_osfRestore }, - { "osfDelete", XKB_KEY_osfDelete }, - { "SunFA_Grave", XKB_KEY_SunFA_Grave }, - { "SunFA_Circum", XKB_KEY_SunFA_Circum }, - { "SunFA_Tilde", XKB_KEY_SunFA_Tilde }, - { "SunFA_Acute", XKB_KEY_SunFA_Acute }, - { "SunFA_Diaeresis", XKB_KEY_SunFA_Diaeresis }, - { "SunFA_Cedilla", XKB_KEY_SunFA_Cedilla }, - { "SunF36", XKB_KEY_SunF36 }, - { "SunF37", XKB_KEY_SunF37 }, - { "SunSys_Req", XKB_KEY_SunSys_Req }, - { "SunProps", XKB_KEY_SunProps }, - { "SunFront", XKB_KEY_SunFront }, - { "SunCopy", XKB_KEY_SunCopy }, - { "SunOpen", XKB_KEY_SunOpen }, - { "SunPaste", XKB_KEY_SunPaste }, - { "SunCut", XKB_KEY_SunCut }, - { "SunPowerSwitch", XKB_KEY_SunPowerSwitch }, - { "SunAudioLowerVolume", XKB_KEY_SunAudioLowerVolume }, - { "SunAudioMute", XKB_KEY_SunAudioMute }, - { "SunAudioRaiseVolume", XKB_KEY_SunAudioRaiseVolume }, - { "SunVideoDegauss", XKB_KEY_SunVideoDegauss }, - { "SunVideoLowerBrightness", XKB_KEY_SunVideoLowerBrightness }, - { "SunVideoRaiseBrightness", XKB_KEY_SunVideoRaiseBrightness }, - { "SunPowerSwitchShift", XKB_KEY_SunPowerSwitchShift }, - { "XF86Switch_VT_1", XKB_KEY_XF86Switch_VT_1 }, - { "XF86Switch_VT_2", XKB_KEY_XF86Switch_VT_2 }, - { "XF86Switch_VT_3", XKB_KEY_XF86Switch_VT_3 }, - { "XF86Switch_VT_4", XKB_KEY_XF86Switch_VT_4 }, - { "XF86Switch_VT_5", XKB_KEY_XF86Switch_VT_5 }, - { "XF86Switch_VT_6", XKB_KEY_XF86Switch_VT_6 }, - { "XF86Switch_VT_7", XKB_KEY_XF86Switch_VT_7 }, - { "XF86Switch_VT_8", XKB_KEY_XF86Switch_VT_8 }, - { "XF86Switch_VT_9", XKB_KEY_XF86Switch_VT_9 }, - { "XF86Switch_VT_10", XKB_KEY_XF86Switch_VT_10 }, - { "XF86Switch_VT_11", XKB_KEY_XF86Switch_VT_11 }, - { "XF86Switch_VT_12", XKB_KEY_XF86Switch_VT_12 }, - { "XF86Ungrab", XKB_KEY_XF86Ungrab }, - { "XF86ClearGrab", XKB_KEY_XF86ClearGrab }, - { "XF86Next_VMode", XKB_KEY_XF86Next_VMode }, - { "XF86Prev_VMode", XKB_KEY_XF86Prev_VMode }, - { "XF86LogWindowTree", XKB_KEY_XF86LogWindowTree }, - { "XF86LogGrabInfo", XKB_KEY_XF86LogGrabInfo }, - { "XF86ModeLock", XKB_KEY_XF86ModeLock }, - { "XF86MonBrightnessUp", XKB_KEY_XF86MonBrightnessUp }, - { "XF86MonBrightnessDown", XKB_KEY_XF86MonBrightnessDown }, - { "XF86KbdLightOnOff", XKB_KEY_XF86KbdLightOnOff }, - { "XF86KbdBrightnessUp", XKB_KEY_XF86KbdBrightnessUp }, - { "XF86KbdBrightnessDown", XKB_KEY_XF86KbdBrightnessDown }, - { "XF86Standby", XKB_KEY_XF86Standby }, - { "XF86AudioLowerVolume", XKB_KEY_XF86AudioLowerVolume }, - { "XF86AudioMute", XKB_KEY_XF86AudioMute }, - { "XF86AudioRaiseVolume", XKB_KEY_XF86AudioRaiseVolume }, - { "XF86AudioPlay", XKB_KEY_XF86AudioPlay }, - { "XF86AudioStop", XKB_KEY_XF86AudioStop }, - { "XF86AudioPrev", XKB_KEY_XF86AudioPrev }, - { "XF86AudioNext", XKB_KEY_XF86AudioNext }, - { "XF86HomePage", XKB_KEY_XF86HomePage }, - { "XF86Mail", XKB_KEY_XF86Mail }, - { "XF86Start", XKB_KEY_XF86Start }, - { "XF86Search", XKB_KEY_XF86Search }, - { "XF86AudioRecord", XKB_KEY_XF86AudioRecord }, - { "XF86Calculator", XKB_KEY_XF86Calculator }, - { "XF86Memo", XKB_KEY_XF86Memo }, - { "XF86ToDoList", XKB_KEY_XF86ToDoList }, - { "XF86Calendar", XKB_KEY_XF86Calendar }, - { "XF86PowerDown", XKB_KEY_XF86PowerDown }, - { "XF86ContrastAdjust", XKB_KEY_XF86ContrastAdjust }, - { "XF86RockerUp", XKB_KEY_XF86RockerUp }, - { "XF86RockerDown", XKB_KEY_XF86RockerDown }, - { "XF86RockerEnter", XKB_KEY_XF86RockerEnter }, - { "XF86Back", XKB_KEY_XF86Back }, - { "XF86Forward", XKB_KEY_XF86Forward }, - { "XF86Stop", XKB_KEY_XF86Stop }, - { "XF86Refresh", XKB_KEY_XF86Refresh }, - { "XF86PowerOff", XKB_KEY_XF86PowerOff }, - { "XF86WakeUp", XKB_KEY_XF86WakeUp }, - { "XF86Eject", XKB_KEY_XF86Eject }, - { "XF86ScreenSaver", XKB_KEY_XF86ScreenSaver }, - { "XF86WWW", XKB_KEY_XF86WWW }, - { "XF86Sleep", XKB_KEY_XF86Sleep }, - { "XF86Favorites", XKB_KEY_XF86Favorites }, - { "XF86AudioPause", XKB_KEY_XF86AudioPause }, - { "XF86AudioMedia", XKB_KEY_XF86AudioMedia }, - { "XF86MyComputer", XKB_KEY_XF86MyComputer }, - { "XF86VendorHome", XKB_KEY_XF86VendorHome }, - { "XF86LightBulb", XKB_KEY_XF86LightBulb }, - { "XF86Shop", XKB_KEY_XF86Shop }, - { "XF86History", XKB_KEY_XF86History }, - { "XF86OpenURL", XKB_KEY_XF86OpenURL }, - { "XF86AddFavorite", XKB_KEY_XF86AddFavorite }, - { "XF86HotLinks", XKB_KEY_XF86HotLinks }, - { "XF86BrightnessAdjust", XKB_KEY_XF86BrightnessAdjust }, - { "XF86Finance", XKB_KEY_XF86Finance }, - { "XF86Community", XKB_KEY_XF86Community }, - { "XF86AudioRewind", XKB_KEY_XF86AudioRewind }, - { "XF86BackForward", XKB_KEY_XF86BackForward }, - { "XF86Launch0", XKB_KEY_XF86Launch0 }, - { "XF86Launch1", XKB_KEY_XF86Launch1 }, - { "XF86Launch2", XKB_KEY_XF86Launch2 }, - { "XF86Launch3", XKB_KEY_XF86Launch3 }, - { "XF86Launch4", XKB_KEY_XF86Launch4 }, - { "XF86Launch5", XKB_KEY_XF86Launch5 }, - { "XF86Launch6", XKB_KEY_XF86Launch6 }, - { "XF86Launch7", XKB_KEY_XF86Launch7 }, - { "XF86Launch8", XKB_KEY_XF86Launch8 }, - { "XF86Launch9", XKB_KEY_XF86Launch9 }, - { "XF86LaunchA", XKB_KEY_XF86LaunchA }, - { "XF86LaunchB", XKB_KEY_XF86LaunchB }, - { "XF86LaunchC", XKB_KEY_XF86LaunchC }, - { "XF86LaunchD", XKB_KEY_XF86LaunchD }, - { "XF86LaunchE", XKB_KEY_XF86LaunchE }, - { "XF86LaunchF", XKB_KEY_XF86LaunchF }, - { "XF86ApplicationLeft", XKB_KEY_XF86ApplicationLeft }, - { "XF86ApplicationRight", XKB_KEY_XF86ApplicationRight }, - { "XF86Book", XKB_KEY_XF86Book }, - { "XF86CD", XKB_KEY_XF86CD }, - { "XF86Calculater", XKB_KEY_XF86Calculater }, - { "XF86Clear", XKB_KEY_XF86Clear }, - { "XF86Close", XKB_KEY_XF86Close }, - { "XF86Copy", XKB_KEY_XF86Copy }, - { "XF86Cut", XKB_KEY_XF86Cut }, - { "XF86Display", XKB_KEY_XF86Display }, - { "XF86DOS", XKB_KEY_XF86DOS }, - { "XF86Documents", XKB_KEY_XF86Documents }, - { "XF86Excel", XKB_KEY_XF86Excel }, - { "XF86Explorer", XKB_KEY_XF86Explorer }, - { "XF86Game", XKB_KEY_XF86Game }, - { "XF86Go", XKB_KEY_XF86Go }, - { "XF86iTouch", XKB_KEY_XF86iTouch }, - { "XF86LogOff", XKB_KEY_XF86LogOff }, - { "XF86Market", XKB_KEY_XF86Market }, - { "XF86Meeting", XKB_KEY_XF86Meeting }, - { "XF86MenuKB", XKB_KEY_XF86MenuKB }, - { "XF86MenuPB", XKB_KEY_XF86MenuPB }, - { "XF86MySites", XKB_KEY_XF86MySites }, - { "XF86New", XKB_KEY_XF86New }, - { "XF86News", XKB_KEY_XF86News }, - { "XF86OfficeHome", XKB_KEY_XF86OfficeHome }, - { "XF86Open", XKB_KEY_XF86Open }, - { "XF86Option", XKB_KEY_XF86Option }, - { "XF86Paste", XKB_KEY_XF86Paste }, - { "XF86Phone", XKB_KEY_XF86Phone }, - { "XF86Q", XKB_KEY_XF86Q }, - { "XF86Reply", XKB_KEY_XF86Reply }, - { "XF86Reload", XKB_KEY_XF86Reload }, - { "XF86RotateWindows", XKB_KEY_XF86RotateWindows }, - { "XF86RotationPB", XKB_KEY_XF86RotationPB }, - { "XF86RotationKB", XKB_KEY_XF86RotationKB }, - { "XF86Save", XKB_KEY_XF86Save }, - { "XF86ScrollUp", XKB_KEY_XF86ScrollUp }, - { "XF86ScrollDown", XKB_KEY_XF86ScrollDown }, - { "XF86ScrollClick", XKB_KEY_XF86ScrollClick }, - { "XF86Send", XKB_KEY_XF86Send }, - { "XF86Spell", XKB_KEY_XF86Spell }, - { "XF86SplitScreen", XKB_KEY_XF86SplitScreen }, - { "XF86Support", XKB_KEY_XF86Support }, - { "XF86TaskPane", XKB_KEY_XF86TaskPane }, - { "XF86Terminal", XKB_KEY_XF86Terminal }, - { "XF86Tools", XKB_KEY_XF86Tools }, - { "XF86Travel", XKB_KEY_XF86Travel }, - { "XF86UserPB", XKB_KEY_XF86UserPB }, - { "XF86User1KB", XKB_KEY_XF86User1KB }, - { "XF86User2KB", XKB_KEY_XF86User2KB }, - { "XF86Video", XKB_KEY_XF86Video }, - { "XF86WheelButton", XKB_KEY_XF86WheelButton }, - { "XF86Word", XKB_KEY_XF86Word }, - { "XF86Xfer", XKB_KEY_XF86Xfer }, - { "XF86ZoomIn", XKB_KEY_XF86ZoomIn }, - { "XF86ZoomOut", XKB_KEY_XF86ZoomOut }, - { "XF86Away", XKB_KEY_XF86Away }, - { "XF86Messenger", XKB_KEY_XF86Messenger }, - { "XF86WebCam", XKB_KEY_XF86WebCam }, - { "XF86MailForward", XKB_KEY_XF86MailForward }, - { "XF86Pictures", XKB_KEY_XF86Pictures }, - { "XF86Music", XKB_KEY_XF86Music }, - { "XF86Battery", XKB_KEY_XF86Battery }, - { "XF86Bluetooth", XKB_KEY_XF86Bluetooth }, - { "XF86WLAN", XKB_KEY_XF86WLAN }, - { "XF86UWB", XKB_KEY_XF86UWB }, - { "XF86AudioForward", XKB_KEY_XF86AudioForward }, - { "XF86AudioRepeat", XKB_KEY_XF86AudioRepeat }, - { "XF86AudioRandomPlay", XKB_KEY_XF86AudioRandomPlay }, - { "XF86Subtitle", XKB_KEY_XF86Subtitle }, - { "XF86AudioCycleTrack", XKB_KEY_XF86AudioCycleTrack }, - { "XF86CycleAngle", XKB_KEY_XF86CycleAngle }, - { "XF86FrameBack", XKB_KEY_XF86FrameBack }, - { "XF86FrameForward", XKB_KEY_XF86FrameForward }, - { "XF86Time", XKB_KEY_XF86Time }, - { "XF86Select", XKB_KEY_XF86Select }, - { "XF86View", XKB_KEY_XF86View }, - { "XF86TopMenu", XKB_KEY_XF86TopMenu }, - { "XF86Red", XKB_KEY_XF86Red }, - { "XF86Green", XKB_KEY_XF86Green }, - { "XF86Yellow", XKB_KEY_XF86Yellow }, - { "XF86Blue", XKB_KEY_XF86Blue }, - { "XF86Suspend", XKB_KEY_XF86Suspend }, - { "XF86Hibernate", XKB_KEY_XF86Hibernate }, - { "XF86TouchpadToggle", XKB_KEY_XF86TouchpadToggle }, - { "XF86TouchpadOn", XKB_KEY_XF86TouchpadOn }, - { "XF86TouchpadOff", XKB_KEY_XF86TouchpadOff }, + { 0x00000000, 20091 }, /* NoSymbol */ + { 0x00000020, 23803 }, /* space */ + { 0x00000021, 12099 }, /* exclam */ + { 0x00000022, 22187 }, /* quotedbl */ + { 0x00000023, 20178 }, /* numbersign */ + { 0x00000024, 11251 }, /* dollar */ + { 0x00000025, 21487 }, /* percent */ + { 0x00000026, 908 }, /* ampersand */ + { 0x00000027, 934 }, /* apostrophe */ + { 0x00000028, 21425 }, /* parenleft */ + { 0x00000029, 21435 }, /* parenright */ + { 0x0000002a, 3283 }, /* asterisk */ + { 0x0000002b, 21557 }, /* plus */ + { 0x0000002c, 8680 }, /* comma */ + { 0x0000002d, 19733 }, /* minus */ + { 0x0000002e, 21495 }, /* period */ + { 0x0000002f, 23768 }, /* slash */ + { 0x00000030, 0 }, /* 0 */ + { 0x00000031, 2 }, /* 1 */ + { 0x00000032, 4 }, /* 2 */ + { 0x00000033, 6 }, /* 3 */ + { 0x00000034, 386 }, /* 4 */ + { 0x00000035, 388 }, /* 5 */ + { 0x00000036, 390 }, /* 6 */ + { 0x00000037, 392 }, /* 7 */ + { 0x00000038, 394 }, /* 8 */ + { 0x00000039, 396 }, /* 9 */ + { 0x0000003a, 8664 }, /* colon */ + { 0x0000003b, 22734 }, /* semicolon */ + { 0x0000003c, 19412 }, /* less */ + { 0x0000003d, 12051 }, /* equal */ + { 0x0000003e, 13272 }, /* greater */ + { 0x0000003f, 22165 }, /* question */ + { 0x00000040, 3292 }, /* at */ + { 0x00000041, 398 }, /* A */ + { 0x00000042, 3328 }, /* B */ + { 0x00000043, 8439 }, /* C */ + { 0x00000044, 10320 }, /* D */ + { 0x00000045, 11424 }, /* E */ + { 0x00000046, 12155 }, /* F */ + { 0x00000047, 12665 }, /* G */ + { 0x00000048, 14378 }, /* H */ + { 0x00000049, 17069 }, /* I */ + { 0x0000004a, 18114 }, /* J */ + { 0x0000004b, 18146 }, /* K */ + { 0x0000004c, 19112 }, /* L */ + { 0x0000004d, 19533 }, /* M */ + { 0x0000004e, 19943 }, /* N */ + { 0x0000004f, 20200 }, /* O */ + { 0x00000050, 21373 }, /* P */ + { 0x00000051, 22156 }, /* Q */ + { 0x00000052, 22217 }, /* R */ + { 0x00000053, 22579 }, /* S */ + { 0x00000054, 24294 }, /* T */ + { 0x00000055, 25847 }, /* U */ + { 0x00000056, 26483 }, /* V */ + { 0x00000057, 26545 }, /* W */ + { 0x00000058, 26631 }, /* X */ + { 0x00000059, 28972 }, /* Y */ + { 0x0000005a, 29100 }, /* Z */ + { 0x0000005b, 3603 }, /* bracketleft */ + { 0x0000005c, 3352 }, /* backslash */ + { 0x0000005d, 3615 }, /* bracketright */ + { 0x0000005e, 3260 }, /* asciicircum */ + { 0x0000005f, 26346 }, /* underscore */ + { 0x00000060, 13266 }, /* grave */ + { 0x00000061, 400 }, /* a */ + { 0x00000062, 3330 }, /* b */ + { 0x00000063, 8441 }, /* c */ + { 0x00000064, 10322 }, /* d */ + { 0x00000065, 11426 }, /* e */ + { 0x00000066, 12157 }, /* f */ + { 0x00000067, 12667 }, /* g */ + { 0x00000068, 14380 }, /* h */ + { 0x00000069, 17071 }, /* i */ + { 0x0000006a, 18116 }, /* j */ + { 0x0000006b, 18148 }, /* k */ + { 0x0000006c, 19114 }, /* l */ + { 0x0000006d, 19535 }, /* m */ + { 0x0000006e, 19945 }, /* n */ + { 0x0000006f, 20202 }, /* o */ + { 0x00000070, 21375 }, /* p */ + { 0x00000071, 22158 }, /* q */ + { 0x00000072, 22219 }, /* r */ + { 0x00000073, 22581 }, /* s */ + { 0x00000074, 24296 }, /* t */ + { 0x00000075, 25849 }, /* u */ + { 0x00000076, 26485 }, /* v */ + { 0x00000077, 26547 }, /* w */ + { 0x00000078, 26633 }, /* x */ + { 0x00000079, 28974 }, /* y */ + { 0x0000007a, 29102 }, /* z */ + { 0x0000007b, 3582 }, /* braceleft */ + { 0x0000007c, 3392 }, /* bar */ + { 0x0000007d, 3592 }, /* braceright */ + { 0x0000007e, 3272 }, /* asciitilde */ + { 0x000000a0, 20078 }, /* nobreakspace */ + { 0x000000a1, 12106 }, /* exclamdown */ + { 0x000000a2, 8589 }, /* cent */ + { 0x000000a3, 23827 }, /* sterling */ + { 0x000000a4, 8766 }, /* currency */ + { 0x000000a5, 29056 }, /* yen */ + { 0x000000a6, 8389 }, /* brokenbar */ + { 0x000000a7, 22719 }, /* section */ + { 0x000000a8, 11203 }, /* diaeresis */ + { 0x000000a9, 8717 }, /* copyright */ + { 0x000000aa, 20852 }, /* ordfeminine */ + { 0x000000ab, 14349 }, /* guillemotleft */ + { 0x000000ac, 20147 }, /* notsign */ + { 0x000000ad, 17062 }, /* hyphen */ + { 0x000000ae, 22331 }, /* registered */ + { 0x000000af, 19641 }, /* macron */ + { 0x000000b0, 11153 }, /* degree */ + { 0x000000b1, 21562 }, /* plusminus */ + { 0x000000b2, 25825 }, /* twosuperior */ + { 0x000000b3, 25571 }, /* threesuperior */ + { 0x000000b4, 820 }, /* acute */ + { 0x000000b5, 19799 }, /* mu */ + { 0x000000b6, 21415 }, /* paragraph */ + { 0x000000b7, 21502 }, /* periodcentered */ + { 0x000000b8, 8581 }, /* cedilla */ + { 0x000000b9, 20755 }, /* onesuperior */ + { 0x000000ba, 19688 }, /* masculine */ + { 0x000000bb, 14363 }, /* guillemotright */ + { 0x000000bc, 20722 }, /* onequarter */ + { 0x000000bd, 20714 }, /* onehalf */ + { 0x000000be, 25542 }, /* threequarters */ + { 0x000000bf, 22174 }, /* questiondown */ + { 0x000000c0, 854 }, /* Agrave */ + { 0x000000c1, 402 }, /* Aacute */ + { 0x000000c2, 622 }, /* Acircumflex */ + { 0x000000c3, 3295 }, /* Atilde */ + { 0x000000c4, 826 }, /* Adiaeresis */ + { 0x000000c5, 2036 }, /* Aring */ + { 0x000000c6, 848 }, /* AE */ + { 0x000000c7, 8539 }, /* Ccedilla */ + { 0x000000c8, 11724 }, /* Egrave */ + { 0x000000c9, 11448 }, /* Eacute */ + { 0x000000ca, 11496 }, /* Ecircumflex */ + { 0x000000cb, 11702 }, /* Ediaeresis */ + { 0x000000cc, 17205 }, /* Igrave */ + { 0x000000cd, 17083 }, /* Iacute */ + { 0x000000ce, 17131 }, /* Icircumflex */ + { 0x000000cf, 17165 }, /* Idiaeresis */ + { 0x000000d0, 12064 }, /* ETH */ + { 0x000000d1, 20155 }, /* Ntilde */ + { 0x000000d2, 20527 }, /* Ograve */ + { 0x000000d3, 20204 }, /* Oacute */ + { 0x000000d4, 20268 }, /* Ocircumflex */ + { 0x000000d5, 21310 }, /* Otilde */ + { 0x000000d6, 20466 }, /* Odiaeresis */ + { 0x000000d7, 19839 }, /* multiply */ + { 0x000000d8, 21296 }, /* Oslash */ + { 0x000000d9, 25971 }, /* Ugrave */ + { 0x000000da, 25851 }, /* Uacute */ + { 0x000000db, 25899 }, /* Ucircumflex */ + { 0x000000dc, 25923 }, /* Udiaeresis */ + { 0x000000dd, 28976 }, /* Yacute */ + { 0x000000de, 25499 }, /* THORN */ + { 0x000000df, 23820 }, /* ssharp */ + { 0x000000e0, 861 }, /* agrave */ + { 0x000000e1, 409 }, /* aacute */ + { 0x000000e2, 634 }, /* acircumflex */ + { 0x000000e3, 3302 }, /* atilde */ + { 0x000000e4, 837 }, /* adiaeresis */ + { 0x000000e5, 2042 }, /* aring */ + { 0x000000e6, 851 }, /* ae */ + { 0x000000e7, 8548 }, /* ccedilla */ + { 0x000000e8, 11731 }, /* egrave */ + { 0x000000e9, 11455 }, /* eacute */ + { 0x000000ea, 11508 }, /* ecircumflex */ + { 0x000000eb, 11713 }, /* ediaeresis */ + { 0x000000ec, 17212 }, /* igrave */ + { 0x000000ed, 17090 }, /* iacute */ + { 0x000000ee, 17143 }, /* icircumflex */ + { 0x000000ef, 17176 }, /* idiaeresis */ + { 0x000000f0, 12072 }, /* eth */ + { 0x000000f1, 20162 }, /* ntilde */ + { 0x000000f2, 20534 }, /* ograve */ + { 0x000000f3, 20211 }, /* oacute */ + { 0x000000f4, 20280 }, /* ocircumflex */ + { 0x000000f5, 21317 }, /* otilde */ + { 0x000000f6, 20477 }, /* odiaeresis */ + { 0x000000f7, 11242 }, /* division */ + { 0x000000f8, 21303 }, /* oslash */ + { 0x000000f9, 25978 }, /* ugrave */ + { 0x000000fa, 25858 }, /* uacute */ + { 0x000000fb, 25911 }, /* ucircumflex */ + { 0x000000fc, 25934 }, /* udiaeresis */ + { 0x000000fd, 28983 }, /* yacute */ + { 0x000000fe, 25511 }, /* thorn */ + { 0x000000ff, 29034 }, /* ydiaeresis */ + { 0x000001a1, 918 }, /* Aogonek */ + { 0x000001a2, 8383 }, /* breve */ + { 0x000001a3, 19517 }, /* Lstroke */ + { 0x000001a5, 19212 }, /* Lcaron */ + { 0x000001a6, 22603 }, /* Sacute */ + { 0x000001a9, 22617 }, /* Scaron */ + { 0x000001aa, 22631 }, /* Scedilla */ + { 0x000001ab, 24322 }, /* Tcaron */ + { 0x000001ac, 29124 }, /* Zacute */ + { 0x000001ae, 29138 }, /* Zcaron */ + { 0x000001af, 29104 }, /* Zabovedot */ + { 0x000001b1, 926 }, /* aogonek */ + { 0x000001b2, 20520 }, /* ogonek */ + { 0x000001b3, 19525 }, /* lstroke */ + { 0x000001b5, 19219 }, /* lcaron */ + { 0x000001b6, 22610 }, /* sacute */ + { 0x000001b7, 8519 }, /* caron */ + { 0x000001b9, 22624 }, /* scaron */ + { 0x000001ba, 22640 }, /* scedilla */ + { 0x000001bb, 24329 }, /* tcaron */ + { 0x000001bc, 29131 }, /* zacute */ + { 0x000001bd, 11283 }, /* doubleacute */ + { 0x000001be, 29145 }, /* zcaron */ + { 0x000001bf, 29114 }, /* zabovedot */ + { 0x000001c0, 22272 }, /* Racute */ + { 0x000001c3, 445 }, /* Abreve */ + { 0x000001c5, 19147 }, /* Lacute */ + { 0x000001c6, 8475 }, /* Cacute */ + { 0x000001c8, 8525 }, /* Ccaron */ + { 0x000001ca, 12035 }, /* Eogonek */ + { 0x000001cc, 11482 }, /* Ecaron */ + { 0x000001cf, 10365 }, /* Dcaron */ + { 0x000001d0, 11401 }, /* Dstroke */ + { 0x000001d1, 19953 }, /* Nacute */ + { 0x000001d2, 19977 }, /* Ncaron */ + { 0x000001d5, 20488 }, /* Odoubleacute */ + { 0x000001d8, 22294 }, /* Rcaron */ + { 0x000001d9, 26452 }, /* Uring */ + { 0x000001db, 25945 }, /* Udoubleacute */ + { 0x000001de, 24336 }, /* Tcedilla */ + { 0x000001e0, 22279 }, /* racute */ + { 0x000001e3, 452 }, /* abreve */ + { 0x000001e5, 19154 }, /* lacute */ + { 0x000001e6, 8482 }, /* cacute */ + { 0x000001e8, 8532 }, /* ccaron */ + { 0x000001ea, 12043 }, /* eogonek */ + { 0x000001ec, 11489 }, /* ecaron */ + { 0x000001ef, 10372 }, /* dcaron */ + { 0x000001f0, 11409 }, /* dstroke */ + { 0x000001f1, 19960 }, /* nacute */ + { 0x000001f2, 19984 }, /* ncaron */ + { 0x000001f5, 20501 }, /* odoubleacute */ + { 0x000001f8, 22301 }, /* rcaron */ + { 0x000001f9, 26458 }, /* uring */ + { 0x000001fb, 25958 }, /* udoubleacute */ + { 0x000001fe, 24345 }, /* tcedilla */ + { 0x000001ff, 436 }, /* abovedot */ + { 0x000002a1, 17027 }, /* Hstroke */ + { 0x000002a6, 16056 }, /* Hcircumflex */ + { 0x000002a9, 17073 }, /* Iabovedot */ + { 0x000002ab, 12689 }, /* Gbreve */ + { 0x000002ac, 18118 }, /* Jcircumflex */ + { 0x000002b1, 17035 }, /* hstroke */ + { 0x000002b6, 16068 }, /* hcircumflex */ + { 0x000002b9, 17187 }, /* idotless */ + { 0x000002bb, 12696 }, /* gbreve */ + { 0x000002bc, 18130 }, /* jcircumflex */ + { 0x000002c5, 8455 }, /* Cabovedot */ + { 0x000002c6, 8557 }, /* Ccircumflex */ + { 0x000002d5, 12669 }, /* Gabovedot */ + { 0x000002d8, 12735 }, /* Gcircumflex */ + { 0x000002dd, 25885 }, /* Ubreve */ + { 0x000002de, 22661 }, /* Scircumflex */ + { 0x000002e5, 8465 }, /* cabovedot */ + { 0x000002e6, 8569 }, /* ccircumflex */ + { 0x000002f5, 12679 }, /* gabovedot */ + { 0x000002f8, 12747 }, /* gcircumflex */ + { 0x000002fd, 25892 }, /* ubreve */ + { 0x000002fe, 22673 }, /* scircumflex */ + { 0x000003a2, 19108 }, /* kra */ + { 0x000003a3, 22308 }, /* Rcedilla */ + { 0x000003a5, 18100 }, /* Itilde */ + { 0x000003a6, 19226 }, /* Lcedilla */ + { 0x000003aa, 11839 }, /* Emacron */ + { 0x000003ab, 12717 }, /* Gcedilla */ + { 0x000003ac, 25788 }, /* Tslash */ + { 0x000003b3, 22317 }, /* rcedilla */ + { 0x000003b5, 18107 }, /* itilde */ + { 0x000003b6, 19235 }, /* lcedilla */ + { 0x000003ba, 11847 }, /* emacron */ + { 0x000003bb, 12726 }, /* gcedilla */ + { 0x000003bc, 25795 }, /* tslash */ + { 0x000003bd, 11983 }, /* ENG */ + { 0x000003bf, 11987 }, /* eng */ + { 0x000003c0, 892 }, /* Amacron */ + { 0x000003c7, 17338 }, /* Iogonek */ + { 0x000003cc, 11428 }, /* Eabovedot */ + { 0x000003cf, 17231 }, /* Imacron */ + { 0x000003d1, 19991 }, /* Ncedilla */ + { 0x000003d2, 20679 }, /* Omacron */ + { 0x000003d3, 18779 }, /* Kcedilla */ + { 0x000003d9, 26368 }, /* Uogonek */ + { 0x000003dd, 26469 }, /* Utilde */ + { 0x000003de, 26321 }, /* Umacron */ + { 0x000003e0, 900 }, /* amacron */ + { 0x000003e7, 17346 }, /* iogonek */ + { 0x000003ec, 11438 }, /* eabovedot */ + { 0x000003ef, 17239 }, /* imacron */ + { 0x000003f1, 20000 }, /* ncedilla */ + { 0x000003f2, 20687 }, /* omacron */ + { 0x000003f3, 18788 }, /* kcedilla */ + { 0x000003f9, 26376 }, /* uogonek */ + { 0x000003fd, 26476 }, /* utilde */ + { 0x000003fe, 26329 }, /* umacron */ + { 0x0000047e, 21364 }, /* overline */ + { 0x000004a1, 18243 }, /* kana_fullstop */ + { 0x000004a2, 18477 }, /* kana_openingbracket */ + { 0x000004a3, 18173 }, /* kana_closingbracket */ + { 0x000004a4, 18193 }, /* kana_comma */ + { 0x000004a5, 18204 }, /* kana_conjunctive */ + { 0x000004a6, 18689 }, /* kana_WO */ + { 0x000004a7, 18150 }, /* kana_a */ + { 0x000004a8, 18297 }, /* kana_i */ + { 0x000004a9, 18667 }, /* kana_u */ + { 0x000004aa, 18221 }, /* kana_e */ + { 0x000004ab, 18463 }, /* kana_o */ + { 0x000004ac, 18697 }, /* kana_ya */ + { 0x000004ad, 18729 }, /* kana_yu */ + { 0x000004ae, 18713 }, /* kana_yo */ + { 0x000004af, 18633 }, /* kana_tsu */ + { 0x000004b0, 22130 }, /* prolongedsound */ + { 0x000004b1, 18157 }, /* kana_A */ + { 0x000004b2, 18304 }, /* kana_I */ + { 0x000004b3, 18674 }, /* kana_U */ + { 0x000004b4, 18228 }, /* kana_E */ + { 0x000004b5, 18470 }, /* kana_O */ + { 0x000004b6, 18311 }, /* kana_KA */ + { 0x000004b7, 18327 }, /* kana_KI */ + { 0x000004b8, 18343 }, /* kana_KU */ + { 0x000004b9, 18319 }, /* kana_KE */ + { 0x000004ba, 18335 }, /* kana_KO */ + { 0x000004bb, 18537 }, /* kana_SA */ + { 0x000004bc, 18553 }, /* kana_SHI */ + { 0x000004bd, 18581 }, /* kana_SU */ + { 0x000004be, 18545 }, /* kana_SE */ + { 0x000004bf, 18573 }, /* kana_SO */ + { 0x000004c0, 18601 }, /* kana_TA */ + { 0x000004c1, 18164 }, /* kana_CHI */ + { 0x000004c2, 18642 }, /* kana_TSU */ + { 0x000004c3, 18609 }, /* kana_TE */ + { 0x000004c4, 18625 }, /* kana_TO */ + { 0x000004c5, 18423 }, /* kana_NA */ + { 0x000004c6, 18439 }, /* kana_NI */ + { 0x000004c7, 18455 }, /* kana_NU */ + { 0x000004c8, 18431 }, /* kana_NE */ + { 0x000004c9, 18447 }, /* kana_NO */ + { 0x000004ca, 18257 }, /* kana_HA */ + { 0x000004cb, 18273 }, /* kana_HI */ + { 0x000004cc, 18235 }, /* kana_FU */ + { 0x000004cd, 18265 }, /* kana_HE */ + { 0x000004ce, 18281 }, /* kana_HO */ + { 0x000004cf, 18361 }, /* kana_MA */ + { 0x000004d0, 18377 }, /* kana_MI */ + { 0x000004d1, 18408 }, /* kana_MU */ + { 0x000004d2, 18369 }, /* kana_ME */ + { 0x000004d3, 18400 }, /* kana_MO */ + { 0x000004d4, 18705 }, /* kana_YA */ + { 0x000004d5, 18737 }, /* kana_YU */ + { 0x000004d6, 18721 }, /* kana_YO */ + { 0x000004d7, 18497 }, /* kana_RA */ + { 0x000004d8, 18513 }, /* kana_RI */ + { 0x000004d9, 18529 }, /* kana_RU */ + { 0x000004da, 18505 }, /* kana_RE */ + { 0x000004db, 18521 }, /* kana_RO */ + { 0x000004dc, 18681 }, /* kana_WA */ + { 0x000004dd, 18416 }, /* kana_N */ + { 0x000004de, 26519 }, /* voicedsound */ + { 0x000004df, 22744 }, /* semivoicedsound */ + { 0x000005ac, 1109 }, /* Arabic_comma */ + { 0x000005bb, 1764 }, /* Arabic_semicolon */ + { 0x000005bf, 1698 }, /* Arabic_question_mark */ + { 0x000005c1, 1303 }, /* Arabic_hamza */ + { 0x000005c2, 1599 }, /* Arabic_maddaonalef */ + { 0x000005c3, 1354 }, /* Arabic_hamzaonalef */ + { 0x000005c4, 1373 }, /* Arabic_hamzaonwaw */ + { 0x000005c5, 1409 }, /* Arabic_hamzaunderalef */ + { 0x000005c6, 1391 }, /* Arabic_hamzaonyeh */ + { 0x000005c7, 1067 }, /* Arabic_alef */ + { 0x000005c8, 1098 }, /* Arabic_beh */ + { 0x000005c9, 1909 }, /* Arabic_tehmarbuta */ + { 0x000005ca, 1898 }, /* Arabic_teh */ + { 0x000005cb, 1939 }, /* Arabic_theh */ + { 0x000005cc, 1481 }, /* Arabic_jeem */ + { 0x000005cd, 1292 }, /* Arabic_hah */ + { 0x000005ce, 1557 }, /* Arabic_khah */ + { 0x000005cf, 1133 }, /* Arabic_dal */ + { 0x000005d0, 1927 }, /* Arabic_thal */ + { 0x000005d1, 1719 }, /* Arabic_ra */ + { 0x000005d2, 2024 }, /* Arabic_zain */ + { 0x000005d3, 1752 }, /* Arabic_seen */ + { 0x000005d4, 1795 }, /* Arabic_sheen */ + { 0x000005d5, 1741 }, /* Arabic_sad */ + { 0x000005d6, 1122 }, /* Arabic_dad */ + { 0x000005d7, 1859 }, /* Arabic_tah */ + { 0x000005d8, 2013 }, /* Arabic_zah */ + { 0x000005d9, 1056 }, /* Arabic_ain */ + { 0x000005da, 1269 }, /* Arabic_ghain */ + { 0x000005e0, 1870 }, /* Arabic_tatweel */ + { 0x000005e1, 1231 }, /* Arabic_feh */ + { 0x000005e2, 1687 }, /* Arabic_qaf */ + { 0x000005e3, 1504 }, /* Arabic_kaf */ + { 0x000005e4, 1569 }, /* Arabic_lam */ + { 0x000005e5, 1618 }, /* Arabic_meem */ + { 0x000005e6, 1630 }, /* Arabic_noon */ + { 0x000005e7, 1282 }, /* Arabic_ha */ + { 0x000005e8, 1974 }, /* Arabic_waw */ + { 0x000005e9, 1079 }, /* Arabic_alefmaksura */ + { 0x000005ea, 1985 }, /* Arabic_yeh */ + { 0x000005eb, 1215 }, /* Arabic_fathatan */ + { 0x000005ec, 1157 }, /* Arabic_dammatan */ + { 0x000005ed, 1528 }, /* Arabic_kasratan */ + { 0x000005ee, 1202 }, /* Arabic_fatha */ + { 0x000005ef, 1144 }, /* Arabic_damma */ + { 0x000005f0, 1515 }, /* Arabic_kasra */ + { 0x000005f1, 1781 }, /* Arabic_shadda */ + { 0x000005f2, 1808 }, /* Arabic_sukun */ + { 0x000006a1, 22760 }, /* Serbian_dje */ + { 0x000006a2, 19585 }, /* Macedonia_gje */ + { 0x000006a3, 9456 }, /* Cyrillic_io */ + { 0x000006a4, 26199 }, /* Ukrainian_ie */ + { 0x000006a5, 19557 }, /* Macedonia_dse */ + { 0x000006a6, 26175 }, /* Ukrainian_i */ + { 0x000006a7, 26225 }, /* Ukrainian_yi */ + { 0x000006a8, 9480 }, /* Cyrillic_je */ + { 0x000006a9, 9618 }, /* Cyrillic_lje */ + { 0x000006aa, 9644 }, /* Cyrillic_nje */ + { 0x000006ab, 22878 }, /* Serbian_tshe */ + { 0x000006ac, 19613 }, /* Macedonia_kje */ + { 0x000006ad, 26123 }, /* Ukrainian_ghe_with_upturn */ + { 0x000006ae, 8399 }, /* Byelorussian_shortu */ + { 0x000006af, 8972 }, /* Cyrillic_dzhe */ + { 0x000006b0, 20189 }, /* numerosign */ + { 0x000006b1, 22772 }, /* Serbian_DJE */ + { 0x000006b2, 19599 }, /* Macedonia_GJE */ + { 0x000006b3, 9468 }, /* Cyrillic_IO */ + { 0x000006b4, 26212 }, /* Ukrainian_IE */ + { 0x000006b5, 19571 }, /* Macedonia_DSE */ + { 0x000006b6, 26187 }, /* Ukrainian_I */ + { 0x000006b7, 26238 }, /* Ukrainian_YI */ + { 0x000006b8, 9492 }, /* Cyrillic_JE */ + { 0x000006b9, 9631 }, /* Cyrillic_LJE */ + { 0x000006ba, 9657 }, /* Cyrillic_NJE */ + { 0x000006bb, 22891 }, /* Serbian_TSHE */ + { 0x000006bc, 19627 }, /* Macedonia_KJE */ + { 0x000006bd, 26149 }, /* Ukrainian_GHE_WITH_UPTURN */ + { 0x000006be, 8419 }, /* Byelorussian_SHORTU */ + { 0x000006bf, 8986 }, /* Cyrillic_DZHE */ + { 0x000006c0, 10200 }, /* Cyrillic_yu */ + { 0x000006c1, 8782 }, /* Cyrillic_a */ + { 0x000006c2, 8804 }, /* Cyrillic_be */ + { 0x000006c3, 9952 }, /* Cyrillic_tse */ + { 0x000006c4, 8948 }, /* Cyrillic_de */ + { 0x000006c5, 9432 }, /* Cyrillic_ie */ + { 0x000006c6, 9022 }, /* Cyrillic_ef */ + { 0x000006c7, 9210 }, /* Cyrillic_ghe */ + { 0x000006c8, 9270 }, /* Cyrillic_ha */ + { 0x000006c9, 9374 }, /* Cyrillic_i */ + { 0x000006ca, 9860 }, /* Cyrillic_shorti */ + { 0x000006cb, 9504 }, /* Cyrillic_ka */ + { 0x000006cc, 9046 }, /* Cyrillic_el */ + { 0x000006cd, 9070 }, /* Cyrillic_em */ + { 0x000006ce, 9094 }, /* Cyrillic_en */ + { 0x000006cf, 9670 }, /* Cyrillic_o */ + { 0x000006d0, 9722 }, /* Cyrillic_pe */ + { 0x000006d1, 10148 }, /* Cyrillic_ya */ + { 0x000006d2, 9162 }, /* Cyrillic_er */ + { 0x000006d3, 9186 }, /* Cyrillic_es */ + { 0x000006d4, 9928 }, /* Cyrillic_te */ + { 0x000006d5, 9978 }, /* Cyrillic_u */ + { 0x000006d6, 10248 }, /* Cyrillic_zhe */ + { 0x000006d7, 10124 }, /* Cyrillic_ve */ + { 0x000006d8, 9892 }, /* Cyrillic_softsign */ + { 0x000006d9, 10172 }, /* Cyrillic_yeru */ + { 0x000006da, 10224 }, /* Cyrillic_ze */ + { 0x000006db, 9776 }, /* Cyrillic_sha */ + { 0x000006dc, 9000 }, /* Cyrillic_e */ + { 0x000006dd, 9802 }, /* Cyrillic_shcha */ + { 0x000006de, 8828 }, /* Cyrillic_che */ + { 0x000006df, 9338 }, /* Cyrillic_hardsign */ + { 0x000006e0, 10212 }, /* Cyrillic_YU */ + { 0x000006e1, 8793 }, /* Cyrillic_A */ + { 0x000006e2, 8816 }, /* Cyrillic_BE */ + { 0x000006e3, 9965 }, /* Cyrillic_TSE */ + { 0x000006e4, 8960 }, /* Cyrillic_DE */ + { 0x000006e5, 9444 }, /* Cyrillic_IE */ + { 0x000006e6, 9034 }, /* Cyrillic_EF */ + { 0x000006e7, 9223 }, /* Cyrillic_GHE */ + { 0x000006e8, 9282 }, /* Cyrillic_HA */ + { 0x000006e9, 9385 }, /* Cyrillic_I */ + { 0x000006ea, 9876 }, /* Cyrillic_SHORTI */ + { 0x000006eb, 9516 }, /* Cyrillic_KA */ + { 0x000006ec, 9058 }, /* Cyrillic_EL */ + { 0x000006ed, 9082 }, /* Cyrillic_EM */ + { 0x000006ee, 9106 }, /* Cyrillic_EN */ + { 0x000006ef, 9681 }, /* Cyrillic_O */ + { 0x000006f0, 9734 }, /* Cyrillic_PE */ + { 0x000006f1, 10160 }, /* Cyrillic_YA */ + { 0x000006f2, 9174 }, /* Cyrillic_ER */ + { 0x000006f3, 9198 }, /* Cyrillic_ES */ + { 0x000006f4, 9940 }, /* Cyrillic_TE */ + { 0x000006f5, 9989 }, /* Cyrillic_U */ + { 0x000006f6, 10261 }, /* Cyrillic_ZHE */ + { 0x000006f7, 10136 }, /* Cyrillic_VE */ + { 0x000006f8, 9910 }, /* Cyrillic_SOFTSIGN */ + { 0x000006f9, 10186 }, /* Cyrillic_YERU */ + { 0x000006fa, 10236 }, /* Cyrillic_ZE */ + { 0x000006fb, 9789 }, /* Cyrillic_SHA */ + { 0x000006fc, 9011 }, /* Cyrillic_E */ + { 0x000006fd, 9817 }, /* Cyrillic_SHCHA */ + { 0x000006fe, 8841 }, /* Cyrillic_CHE */ + { 0x000006ff, 9356 }, /* Cyrillic_HARDSIGN */ + { 0x000007a1, 13342 }, /* Greek_ALPHAaccent */ + { 0x000007a2, 13472 }, /* Greek_EPSILONaccent */ + { 0x000007a3, 13532 }, /* Greek_ETAaccent */ + { 0x000007a4, 13647 }, /* Greek_IOTAaccent */ + { 0x000007a5, 13726 }, /* Greek_IOTAdieresis */ + { 0x000007a7, 13962 }, /* Greek_OMICRONaccent */ + { 0x000007a8, 14189 }, /* Greek_UPSILONaccent */ + { 0x000007a9, 14257 }, /* Greek_UPSILONdieresis */ + { 0x000007ab, 13898 }, /* Greek_OMEGAaccent */ + { 0x000007ae, 13297 }, /* Greek_accentdieresis */ + { 0x000007af, 13610 }, /* Greek_horizbar */ + { 0x000007b1, 13360 }, /* Greek_alphaaccent */ + { 0x000007b2, 13492 }, /* Greek_epsilonaccent */ + { 0x000007b3, 13548 }, /* Greek_etaaccent */ + { 0x000007b4, 13664 }, /* Greek_iotaaccent */ + { 0x000007b5, 13745 }, /* Greek_iotadieresis */ + { 0x000007b6, 13681 }, /* Greek_iotaaccentdieresis */ + { 0x000007b7, 13982 }, /* Greek_omicronaccent */ + { 0x000007b8, 14209 }, /* Greek_upsilonaccent */ + { 0x000007b9, 14279 }, /* Greek_upsilondieresis */ + { 0x000007ba, 14229 }, /* Greek_upsilonaccentdieresis */ + { 0x000007bb, 13916 }, /* Greek_omegaaccent */ + { 0x000007c1, 13318 }, /* Greek_ALPHA */ + { 0x000007c2, 13378 }, /* Greek_BETA */ + { 0x000007c3, 13586 }, /* Greek_GAMMA */ + { 0x000007c4, 13420 }, /* Greek_DELTA */ + { 0x000007c5, 13444 }, /* Greek_EPSILON */ + { 0x000007c6, 14319 }, /* Greek_ZETA */ + { 0x000007c7, 13512 }, /* Greek_ETA */ + { 0x000007c8, 14137 }, /* Greek_THETA */ + { 0x000007c9, 13625 }, /* Greek_IOTA */ + { 0x000007ca, 13764 }, /* Greek_KAPPA */ + { 0x000007cb, 13814 }, /* Greek_LAMDA */ + { 0x000007cc, 13838 }, /* Greek_MU */ + { 0x000007cd, 13856 }, /* Greek_NU */ + { 0x000007ce, 14301 }, /* Greek_XI */ + { 0x000007cf, 13934 }, /* Greek_OMICRON */ + { 0x000007d0, 14022 }, /* Greek_PI */ + { 0x000007d1, 14060 }, /* Greek_RHO */ + { 0x000007d2, 14080 }, /* Greek_SIGMA */ + { 0x000007d4, 14117 }, /* Greek_TAU */ + { 0x000007d5, 14161 }, /* Greek_UPSILON */ + { 0x000007d6, 14002 }, /* Greek_PHI */ + { 0x000007d7, 13400 }, /* Greek_CHI */ + { 0x000007d8, 14040 }, /* Greek_PSI */ + { 0x000007d9, 13874 }, /* Greek_OMEGA */ + { 0x000007e1, 13330 }, /* Greek_alpha */ + { 0x000007e2, 13389 }, /* Greek_beta */ + { 0x000007e3, 13598 }, /* Greek_gamma */ + { 0x000007e4, 13432 }, /* Greek_delta */ + { 0x000007e5, 13458 }, /* Greek_epsilon */ + { 0x000007e6, 14330 }, /* Greek_zeta */ + { 0x000007e7, 13522 }, /* Greek_eta */ + { 0x000007e8, 14149 }, /* Greek_theta */ + { 0x000007e9, 13636 }, /* Greek_iota */ + { 0x000007ea, 13776 }, /* Greek_kappa */ + { 0x000007eb, 13826 }, /* Greek_lamda */ + { 0x000007ec, 13847 }, /* Greek_mu */ + { 0x000007ed, 13865 }, /* Greek_nu */ + { 0x000007ee, 14310 }, /* Greek_xi */ + { 0x000007ef, 13948 }, /* Greek_omicron */ + { 0x000007f0, 14031 }, /* Greek_pi */ + { 0x000007f1, 14070 }, /* Greek_rho */ + { 0x000007f2, 14092 }, /* Greek_sigma */ + { 0x000007f3, 13564 }, /* Greek_finalsmallsigma */ + { 0x000007f4, 14127 }, /* Greek_tau */ + { 0x000007f5, 14175 }, /* Greek_upsilon */ + { 0x000007f6, 14012 }, /* Greek_phi */ + { 0x000007f7, 13410 }, /* Greek_chi */ + { 0x000007f8, 14050 }, /* Greek_psi */ + { 0x000007f9, 13886 }, /* Greek_omega */ + { 0x000008a1, 19356 }, /* leftradical */ + { 0x000008a2, 25621 }, /* topleftradical */ + { 0x000008a3, 16667 }, /* horizconnector */ + { 0x000008a4, 25595 }, /* topintegral */ + { 0x000008a5, 3422 }, /* botintegral */ + { 0x000008a6, 26505 }, /* vertconnector */ + { 0x000008a7, 25636 }, /* topleftsqbracket */ + { 0x000008a8, 3448 }, /* botleftsqbracket */ + { 0x000008a9, 25685 }, /* toprightsqbracket */ + { 0x000008aa, 3497 }, /* botrightsqbracket */ + { 0x000008ab, 25607 }, /* topleftparens */ + { 0x000008ac, 3434 }, /* botleftparens */ + { 0x000008ad, 25670 }, /* toprightparens */ + { 0x000008ae, 3482 }, /* botrightparens */ + { 0x000008af, 19306 }, /* leftmiddlecurlybrace */ + { 0x000008b0, 22440 }, /* rightmiddlecurlybrace */ + { 0x000008b1, 25653 }, /* topleftsummation */ + { 0x000008b2, 3465 }, /* botleftsummation */ + { 0x000008b3, 25726 }, /* topvertsummationconnector */ + { 0x000008b4, 3538 }, /* botvertsummationconnector */ + { 0x000008b5, 25703 }, /* toprightsummation */ + { 0x000008b6, 3515 }, /* botrightsummation */ + { 0x000008b7, 22462 }, /* rightmiddlesummation */ + { 0x000008bc, 19417 }, /* lessthanequal */ + { 0x000008bd, 20125 }, /* notequal */ + { 0x000008be, 13280 }, /* greaterthanequal */ + { 0x000008bf, 17313 }, /* integral */ + { 0x000008c0, 25479 }, /* therefore */ + { 0x000008c1, 26487 }, /* variation */ + { 0x000008c2, 17275 }, /* infinity */ + { 0x000008c5, 19947 }, /* nabla */ + { 0x000008c8, 954 }, /* approximate */ + { 0x000008c9, 22999 }, /* similarequal */ + { 0x000008cd, 17196 }, /* ifonlyif */ + { 0x000008ce, 17247 }, /* implies */ + { 0x000008cf, 17155 }, /* identical */ + { 0x000008d6, 22286 }, /* radical */ + { 0x000008da, 17255 }, /* includedin */ + { 0x000008db, 17266 }, /* includes */ + { 0x000008dc, 17322 }, /* intersection */ + { 0x000008dd, 26362 }, /* union */ + { 0x000008de, 19457 }, /* logicaland */ + { 0x000008df, 19468 }, /* logicalor */ + { 0x000008ef, 21463 }, /* partialderivative */ + { 0x000008f6, 12656 }, /* function */ + { 0x000008fb, 19266 }, /* leftarrow */ + { 0x000008fc, 26387 }, /* uparrow */ + { 0x000008fd, 22397 }, /* rightarrow */ + { 0x000008fe, 11332 }, /* downarrow */ + { 0x000009df, 3410 }, /* blank */ + { 0x000009e0, 23790 }, /* soliddiamond */ + { 0x000009e1, 8603 }, /* checkerboard */ + { 0x000009e2, 17043 }, /* ht */ + { 0x000009e3, 12413 }, /* ff */ + { 0x000009e4, 8727 }, /* cr */ + { 0x000009e5, 19431 }, /* lf */ + { 0x000009e8, 20075 }, /* nl */ + { 0x000009e9, 26542 }, /* vt */ + { 0x000009ea, 19502 }, /* lowrightcorner */ + { 0x000009eb, 26416 }, /* uprightcorner */ + { 0x000009ec, 26403 }, /* upleftcorner */ + { 0x000009ed, 19488 }, /* lowleftcorner */ + { 0x000009ee, 8730 }, /* crossinglines */ + { 0x000009ef, 16682 }, /* horizlinescan1 */ + { 0x000009f0, 16697 }, /* horizlinescan3 */ + { 0x000009f1, 16712 }, /* horizlinescan5 */ + { 0x000009f2, 16727 }, /* horizlinescan7 */ + { 0x000009f3, 16742 }, /* horizlinescan9 */ + { 0x000009f4, 19397 }, /* leftt */ + { 0x000009f5, 22545 }, /* rightt */ + { 0x000009f6, 3533 }, /* bott */ + { 0x000009f7, 25721 }, /* topt */ + { 0x000009f8, 26497 }, /* vertbar */ + { 0x00000aa1, 11928 }, /* emspace */ + { 0x00000aa2, 12027 }, /* enspace */ + { 0x00000aa3, 11821 }, /* em3space */ + { 0x00000aa4, 11830 }, /* em4space */ + { 0x00000aa5, 11221 }, /* digitspace */ + { 0x00000aa6, 22145 }, /* punctspace */ + { 0x00000aa7, 25489 }, /* thinspace */ + { 0x00000aa8, 14382 }, /* hairspace */ + { 0x00000aa9, 11855 }, /* emdash */ + { 0x00000aaa, 11940 }, /* endash */ + { 0x00000aac, 22987 }, /* signifblank */ + { 0x00000aae, 11812 }, /* ellipsis */ + { 0x00000aaf, 11267 }, /* doubbaselinedot */ + { 0x00000ab0, 20767 }, /* onethird */ + { 0x00000ab1, 25837 }, /* twothirds */ + { 0x00000ab2, 20705 }, /* onefifth */ + { 0x00000ab3, 25802 }, /* twofifths */ + { 0x00000ab4, 25530 }, /* threefifths */ + { 0x00000ab5, 12607 }, /* fourfifths */ + { 0x00000ab6, 20733 }, /* onesixth */ + { 0x00000ab7, 12569 }, /* fivesixths */ + { 0x00000ab8, 8506 }, /* careof */ + { 0x00000abb, 12427 }, /* figdash */ + { 0x00000abc, 19249 }, /* leftanglebracket */ + { 0x00000abd, 11140 }, /* decimalpoint */ + { 0x00000abe, 22379 }, /* rightanglebracket */ + { 0x00000abf, 19681 }, /* marker */ + { 0x00000ac3, 20695 }, /* oneeighth */ + { 0x00000ac4, 25517 }, /* threeeighths */ + { 0x00000ac5, 12557 }, /* fiveeighths */ + { 0x00000ac6, 22904 }, /* seveneighths */ + { 0x00000ac9, 25760 }, /* trademark */ + { 0x00000aca, 22973 }, /* signaturemark */ + { 0x00000acb, 25770 }, /* trademarkincircle */ + { 0x00000acc, 19327 }, /* leftopentriangle */ + { 0x00000acd, 22483 }, /* rightopentriangle */ + { 0x00000ace, 11890 }, /* emopencircle */ + { 0x00000acf, 11903 }, /* emopenrectangle */ + { 0x00000ad0, 19377 }, /* leftsinglequotemark */ + { 0x00000ad1, 22524 }, /* rightsinglequotemark */ + { 0x00000ad2, 19286 }, /* leftdoublequotemark */ + { 0x00000ad3, 22419 }, /* rightdoublequotemark */ + { 0x00000ad4, 22067 }, /* prescription */ + { 0x00000ad5, 21517 }, /* permille */ + { 0x00000ad6, 19739 }, /* minutes */ + { 0x00000ad7, 22711 }, /* seconds */ + { 0x00000ad9, 19181 }, /* latincross */ + { 0x00000ada, 16626 }, /* hexagram */ + { 0x00000adb, 12455 }, /* filledrectbullet */ + { 0x00000adc, 12435 }, /* filledlefttribullet */ + { 0x00000add, 12472 }, /* filledrighttribullet */ + { 0x00000ade, 11862 }, /* emfilledcircle */ + { 0x00000adf, 11877 }, /* emfilledrect */ + { 0x00000ae0, 11991 }, /* enopencircbullet */ + { 0x00000ae1, 12008 }, /* enopensquarebullet */ + { 0x00000ae2, 20794 }, /* openrectbullet */ + { 0x00000ae3, 20836 }, /* opentribulletup */ + { 0x00000ae4, 20818 }, /* opentribulletdown */ + { 0x00000ae5, 20809 }, /* openstar */ + { 0x00000ae6, 11947 }, /* enfilledcircbullet */ + { 0x00000ae7, 11966 }, /* enfilledsqbullet */ + { 0x00000ae8, 12513 }, /* filledtribulletup */ + { 0x00000ae9, 12493 }, /* filledtribulletdown */ + { 0x00000aea, 19344 }, /* leftpointer */ + { 0x00000aeb, 22501 }, /* rightpointer */ + { 0x00000aec, 8649 }, /* club */ + { 0x00000aed, 11213 }, /* diamond */ + { 0x00000aee, 16080 }, /* heart */ + { 0x00000af0, 19668 }, /* maltesecross */ + { 0x00000af1, 10358 }, /* dagger */ + { 0x00000af2, 11295 }, /* doubledagger */ + { 0x00000af3, 8616 }, /* checkmark */ + { 0x00000af4, 3380 }, /* ballotcross */ + { 0x00000af5, 19860 }, /* musicalsharp */ + { 0x00000af6, 19848 }, /* musicalflat */ + { 0x00000af7, 19657 }, /* malesymbol */ + { 0x00000af8, 12400 }, /* femalesymbol */ + { 0x00000af9, 24354 }, /* telephone */ + { 0x00000afa, 24364 }, /* telephonerecorder */ + { 0x00000afb, 21537 }, /* phonographcopyright */ + { 0x00000afc, 8513 }, /* caret */ + { 0x00000afd, 23028 }, /* singlelowquotemark */ + { 0x00000afe, 11308 }, /* doublelowquotemark */ + { 0x00000aff, 8775 }, /* cursor */ + { 0x00000ba3, 19276 }, /* leftcaret */ + { 0x00000ba6, 22408 }, /* rightcaret */ + { 0x00000ba8, 11342 }, /* downcaret */ + { 0x00000ba9, 26395 }, /* upcaret */ + { 0x00000bc0, 21324 }, /* overbar */ + { 0x00000bc2, 11371 }, /* downtack */ + { 0x00000bc3, 26430 }, /* upshoe */ + { 0x00000bc4, 11361 }, /* downstile */ + { 0x00000bc6, 26337 }, /* underbar */ + { 0x00000bca, 18142 }, /* jot */ + { 0x00000bcc, 22160 }, /* quad */ + { 0x00000bce, 26445 }, /* uptack */ + { 0x00000bcf, 8626 }, /* circle */ + { 0x00000bd3, 26437 }, /* upstile */ + { 0x00000bd6, 11352 }, /* downshoe */ + { 0x00000bd8, 22514 }, /* rightshoe */ + { 0x00000bda, 19368 }, /* leftshoe */ + { 0x00000bdc, 19403 }, /* lefttack */ + { 0x00000bfc, 22552 }, /* righttack */ + { 0x00000cdf, 16173 }, /* hebrew_doublelowline */ + { 0x00000ce0, 16086 }, /* hebrew_aleph */ + { 0x00000ce1, 16111 }, /* hebrew_bet */ + { 0x00000ce2, 16292 }, /* hebrew_gimel */ + { 0x00000ce3, 16146 }, /* hebrew_dalet */ + { 0x00000ce4, 16319 }, /* hebrew_he */ + { 0x00000ce5, 16531 }, /* hebrew_waw */ + { 0x00000ce6, 16577 }, /* hebrew_zain */ + { 0x00000ce7, 16134 }, /* hebrew_chet */ + { 0x00000ce8, 16508 }, /* hebrew_tet */ + { 0x00000ce9, 16542 }, /* hebrew_yod */ + { 0x00000cea, 16194 }, /* hebrew_finalkaph */ + { 0x00000ceb, 16340 }, /* hebrew_kaph */ + { 0x00000cec, 16363 }, /* hebrew_lamed */ + { 0x00000ced, 16211 }, /* hebrew_finalmem */ + { 0x00000cee, 16376 }, /* hebrew_mem */ + { 0x00000cef, 16227 }, /* hebrew_finalnun */ + { 0x00000cf0, 16387 }, /* hebrew_nun */ + { 0x00000cf1, 16432 }, /* hebrew_samech */ + { 0x00000cf2, 16099 }, /* hebrew_ayin */ + { 0x00000cf3, 16243 }, /* hebrew_finalpe */ + { 0x00000cf4, 16398 }, /* hebrew_pe */ + { 0x00000cf5, 16258 }, /* hebrew_finalzade */ + { 0x00000cf6, 16553 }, /* hebrew_zade */ + { 0x00000cf7, 16408 }, /* hebrew_qoph */ + { 0x00000cf8, 16420 }, /* hebrew_resh */ + { 0x00000cf9, 16460 }, /* hebrew_shin */ + { 0x00000cfa, 16497 }, /* hebrew_taw */ + { 0x00000da1, 24617 }, /* Thai_kokai */ + { 0x00000da2, 24547 }, /* Thai_khokhai */ + { 0x00000da3, 24573 }, /* Thai_khokhuat */ + { 0x00000da4, 24587 }, /* Thai_khokhwai */ + { 0x00000da5, 24560 }, /* Thai_khokhon */ + { 0x00000da6, 24601 }, /* Thai_khorakhang */ + { 0x00000da7, 24930 }, /* Thai_ngongu */ + { 0x00000da8, 24423 }, /* Thai_chochan */ + { 0x00000da9, 24450 }, /* Thai_choching */ + { 0x00000daa, 24436 }, /* Thai_chochang */ + { 0x00000dab, 25291 }, /* Thai_soso */ + { 0x00000dac, 24464 }, /* Thai_chochoe */ + { 0x00000dad, 25467 }, /* Thai_yoying */ + { 0x00000dae, 24477 }, /* Thai_dochada */ + { 0x00000daf, 25420 }, /* Thai_topatak */ + { 0x00000db0, 25379 }, /* Thai_thothan */ + { 0x00000db1, 25329 }, /* Thai_thonangmontho */ + { 0x00000db2, 25348 }, /* Thai_thophuthao */ + { 0x00000db3, 24956 }, /* Thai_nonen */ + { 0x00000db4, 24490 }, /* Thai_dodek */ + { 0x00000db5, 25433 }, /* Thai_totao */ + { 0x00000db6, 25406 }, /* Thai_thothung */ + { 0x00000db7, 25364 }, /* Thai_thothahan */ + { 0x00000db8, 25392 }, /* Thai_thothong */ + { 0x00000db9, 24967 }, /* Thai_nonu */ + { 0x00000dba, 24409 }, /* Thai_bobaimai */ + { 0x00000dbb, 25058 }, /* Thai_popla */ + { 0x00000dbc, 25028 }, /* Thai_phophung */ + { 0x00000dbd, 24501 }, /* Thai_fofa */ + { 0x00000dbe, 25015 }, /* Thai_phophan */ + { 0x00000dbf, 24511 }, /* Thai_fofan */ + { 0x00000dc0, 25042 }, /* Thai_phosamphao */ + { 0x00000dc1, 24920 }, /* Thai_moma */ + { 0x00000dc2, 25456 }, /* Thai_yoyak */ + { 0x00000dc3, 25069 }, /* Thai_rorua */ + { 0x00000dc4, 25080 }, /* Thai_ru */ + { 0x00000dc5, 24780 }, /* Thai_loling */ + { 0x00000dc6, 24792 }, /* Thai_lu */ + { 0x00000dc7, 25444 }, /* Thai_wowaen */ + { 0x00000dc8, 25279 }, /* Thai_sosala */ + { 0x00000dc9, 25267 }, /* Thai_sorusi */ + { 0x00000dca, 25301 }, /* Thai_sosua */ + { 0x00000dcb, 24522 }, /* Thai_hohip */ + { 0x00000dcc, 24767 }, /* Thai_lochula */ + { 0x00000dcd, 24977 }, /* Thai_oang */ + { 0x00000dce, 24533 }, /* Thai_honokhuk */ + { 0x00000dcf, 24987 }, /* Thai_paiyannoi */ + { 0x00000dd0, 25088 }, /* Thai_saraa */ + { 0x00000dd1, 24828 }, /* Thai_maihanakat */ + { 0x00000dd2, 25099 }, /* Thai_saraaa */ + { 0x00000dd3, 25162 }, /* Thai_saraam */ + { 0x00000dd4, 25185 }, /* Thai_sarai */ + { 0x00000dd5, 25196 }, /* Thai_saraii */ + { 0x00000dd6, 25230 }, /* Thai_saraue */ + { 0x00000dd7, 25242 }, /* Thai_sarauee */ + { 0x00000dd8, 25219 }, /* Thai_sarau */ + { 0x00000dd9, 25255 }, /* Thai_sarauu */ + { 0x00000dda, 25002 }, /* Thai_phinthu */ + { 0x00000dde, 24844 }, /* Thai_maihanakat_maitho */ + { 0x00000ddf, 24399 }, /* Thai_baht */ + { 0x00000de0, 25174 }, /* Thai_sarae */ + { 0x00000de1, 25111 }, /* Thai_saraae */ + { 0x00000de2, 25208 }, /* Thai_sarao */ + { 0x00000de3, 25143 }, /* Thai_saraaimaimuan */ + { 0x00000de4, 25123 }, /* Thai_saraaimaimalai */ + { 0x00000de5, 24628 }, /* Thai_lakkhangyao */ + { 0x00000de6, 24906 }, /* Thai_maiyamok */ + { 0x00000de7, 24867 }, /* Thai_maitaikhu */ + { 0x00000de8, 24817 }, /* Thai_maiek */ + { 0x00000de9, 24882 }, /* Thai_maitho */ + { 0x00000dea, 24894 }, /* Thai_maitri */ + { 0x00000deb, 24800 }, /* Thai_maichattawa */ + { 0x00000dec, 25312 }, /* Thai_thanthakhat */ + { 0x00000ded, 24942 }, /* Thai_nikhahit */ + { 0x00000df0, 24755 }, /* Thai_leksun */ + { 0x00000df1, 24693 }, /* Thai_leknung */ + { 0x00000df2, 24742 }, /* Thai_leksong */ + { 0x00000df3, 24719 }, /* Thai_leksam */ + { 0x00000df4, 24731 }, /* Thai_leksi */ + { 0x00000df5, 24658 }, /* Thai_lekha */ + { 0x00000df6, 24669 }, /* Thai_lekhok */ + { 0x00000df7, 24645 }, /* Thai_lekchet */ + { 0x00000df8, 24706 }, /* Thai_lekpaet */ + { 0x00000df9, 24681 }, /* Thai_lekkao */ + { 0x00000ea1, 15181 }, /* Hangul_Kiyeog */ + { 0x00000ea2, 15726 }, /* Hangul_SsangKiyeog */ + { 0x00000ea3, 15195 }, /* Hangul_KiyeogSios */ + { 0x00000ea4, 15276 }, /* Hangul_Nieun */ + { 0x00000ea5, 15307 }, /* Hangul_NieunJieuj */ + { 0x00000ea6, 15289 }, /* Hangul_NieunHieuh */ + { 0x00000ea7, 14488 }, /* Hangul_Dikeud */ + { 0x00000ea8, 15689 }, /* Hangul_SsangDikeud */ + { 0x00000ea9, 15461 }, /* Hangul_Rieul */ + { 0x00000eaa, 15492 }, /* Hangul_RieulKiyeog */ + { 0x00000eab, 15511 }, /* Hangul_RieulMieum */ + { 0x00000eac, 15548 }, /* Hangul_RieulPieub */ + { 0x00000ead, 15566 }, /* Hangul_RieulSios */ + { 0x00000eae, 15583 }, /* Hangul_RieulTieut */ + { 0x00000eaf, 15529 }, /* Hangul_RieulPhieuf */ + { 0x00000eb0, 15474 }, /* Hangul_RieulHieuh */ + { 0x00000eb1, 15238 }, /* Hangul_Mieum */ + { 0x00000eb2, 15373 }, /* Hangul_Pieub */ + { 0x00000eb3, 15745 }, /* Hangul_SsangPieub */ + { 0x00000eb4, 15386 }, /* Hangul_PieubSios */ + { 0x00000eb5, 15662 }, /* Hangul_Sios */ + { 0x00000eb6, 15763 }, /* Hangul_SsangSios */ + { 0x00000eb7, 14577 }, /* Hangul_Ieung */ + { 0x00000eb8, 15154 }, /* Hangul_Jieuj */ + { 0x00000eb9, 15708 }, /* Hangul_SsangJieuj */ + { 0x00000eba, 14458 }, /* Hangul_Cieuc */ + { 0x00000ebb, 15167 }, /* Hangul_Khieuq */ + { 0x00000ebc, 15883 }, /* Hangul_Tieut */ + { 0x00000ebd, 15359 }, /* Hangul_Phieuf */ + { 0x00000ebe, 14555 }, /* Hangul_Hieuh */ + { 0x00000ebf, 14399 }, /* Hangul_A */ + { 0x00000ec0, 14408 }, /* Hangul_AE */ + { 0x00000ec1, 15957 }, /* Hangul_YA */ + { 0x00000ec2, 15967 }, /* Hangul_YAE */ + { 0x00000ec3, 14522 }, /* Hangul_EO */ + { 0x00000ec4, 14502 }, /* Hangul_E */ + { 0x00000ec5, 15988 }, /* Hangul_YEO */ + { 0x00000ec6, 15978 }, /* Hangul_YE */ + { 0x00000ec7, 15325 }, /* Hangul_O */ + { 0x00000ec8, 15905 }, /* Hangul_WA */ + { 0x00000ec9, 15915 }, /* Hangul_WAE */ + { 0x00000eca, 15334 }, /* Hangul_OE */ + { 0x00000ecb, 16028 }, /* Hangul_YO */ + { 0x00000ecc, 15896 }, /* Hangul_U */ + { 0x00000ecd, 15936 }, /* Hangul_WEO */ + { 0x00000ece, 15926 }, /* Hangul_WE */ + { 0x00000ecf, 15947 }, /* Hangul_WI */ + { 0x00000ed0, 16038 }, /* Hangul_YU */ + { 0x00000ed1, 14532 }, /* Hangul_EU */ + { 0x00000ed2, 16018 }, /* Hangul_YI */ + { 0x00000ed3, 14568 }, /* Hangul_I */ + { 0x00000ed4, 14682 }, /* Hangul_J_Kiyeog */ + { 0x00000ed5, 15052 }, /* Hangul_J_SsangKiyeog */ + { 0x00000ed6, 14698 }, /* Hangul_J_KiyeogSios */ + { 0x00000ed7, 14760 }, /* Hangul_J_Nieun */ + { 0x00000ed8, 14795 }, /* Hangul_J_NieunJieuj */ + { 0x00000ed9, 14775 }, /* Hangul_J_NieunHieuh */ + { 0x00000eda, 14605 }, /* Hangul_J_Dikeud */ + { 0x00000edb, 14882 }, /* Hangul_J_Rieul */ + { 0x00000edc, 14917 }, /* Hangul_J_RieulKiyeog */ + { 0x00000edd, 14938 }, /* Hangul_J_RieulMieum */ + { 0x00000ede, 14979 }, /* Hangul_J_RieulPieub */ + { 0x00000edf, 14999 }, /* Hangul_J_RieulSios */ + { 0x00000ee0, 15018 }, /* Hangul_J_RieulTieut */ + { 0x00000ee1, 14958 }, /* Hangul_J_RieulPhieuf */ + { 0x00000ee2, 14897 }, /* Hangul_J_RieulHieuh */ + { 0x00000ee3, 14745 }, /* Hangul_J_Mieum */ + { 0x00000ee4, 14848 }, /* Hangul_J_Pieub */ + { 0x00000ee5, 14863 }, /* Hangul_J_PieubSios */ + { 0x00000ee6, 15038 }, /* Hangul_J_Sios */ + { 0x00000ee7, 15073 }, /* Hangul_J_SsangSios */ + { 0x00000ee8, 14636 }, /* Hangul_J_Ieung */ + { 0x00000ee9, 14651 }, /* Hangul_J_Jieuj */ + { 0x00000eea, 14590 }, /* Hangul_J_Cieuc */ + { 0x00000eeb, 14666 }, /* Hangul_J_Khieuq */ + { 0x00000eec, 15092 }, /* Hangul_J_Tieut */ + { 0x00000eed, 14832 }, /* Hangul_J_Phieuf */ + { 0x00000eee, 14621 }, /* Hangul_J_Hieuh */ + { 0x00000eef, 15601 }, /* Hangul_RieulYeorinHieuh */ + { 0x00000ef0, 15793 }, /* Hangul_SunkyeongeumMieum */ + { 0x00000ef1, 15844 }, /* Hangul_SunkyeongeumPieub */ + { 0x00000ef2, 15344 }, /* Hangul_PanSios */ + { 0x00000ef3, 15213 }, /* Hangul_KkogjiDalrinIeung */ + { 0x00000ef4, 15818 }, /* Hangul_SunkyeongeumPhieuf */ + { 0x00000ef5, 15999 }, /* Hangul_YeorinHieuh */ + { 0x00000ef6, 14418 }, /* Hangul_AraeA */ + { 0x00000ef7, 14431 }, /* Hangul_AraeAE */ + { 0x00000ef8, 14815 }, /* Hangul_J_PanSios */ + { 0x00000ef9, 14718 }, /* Hangul_J_KkogjiDalrinIeung */ + { 0x00000efa, 15107 }, /* Hangul_J_YeorinHieuh */ + { 0x00000eff, 18797 }, /* Korean_Won */ + { 0x000013bc, 20514 }, /* OE */ + { 0x000013bd, 20517 }, /* oe */ + { 0x000013be, 29045 }, /* Ydiaeresis */ + { 0x000020ac, 12090 }, /* EuroSign */ + { 0x0000fd01, 125 }, /* 3270_Duplicate */ + { 0x0000fd02, 195 }, /* 3270_FieldMark */ + { 0x0000fd03, 343 }, /* 3270_Right2 */ + { 0x0000fd04, 245 }, /* 3270_Left2 */ + { 0x0000fd05, 33 }, /* 3270_BackTab */ + { 0x0000fd06, 151 }, /* 3270_EraseEOF */ + { 0x0000fd07, 165 }, /* 3270_EraseInput */ + { 0x0000fd08, 332 }, /* 3270_Reset */ + { 0x0000fd09, 310 }, /* 3270_Quit */ + { 0x0000fd0a, 256 }, /* 3270_PA1 */ + { 0x0000fd0b, 265 }, /* 3270_PA2 */ + { 0x0000fd0c, 274 }, /* 3270_PA3 */ + { 0x0000fd0d, 376 }, /* 3270_Test */ + { 0x0000fd0e, 23 }, /* 3270_Attn */ + { 0x0000fd0f, 74 }, /* 3270_CursorBlink */ + { 0x0000fd10, 8 }, /* 3270_AltCursor */ + { 0x0000fd11, 231 }, /* 3270_KeyClick */ + { 0x0000fd12, 221 }, /* 3270_Jump */ + { 0x0000fd13, 210 }, /* 3270_Ident */ + { 0x0000fd14, 355 }, /* 3270_Rule */ + { 0x0000fd15, 64 }, /* 3270_Copy */ + { 0x0000fd16, 283 }, /* 3270_Play */ + { 0x0000fd17, 365 }, /* 3270_Setup */ + { 0x0000fd18, 320 }, /* 3270_Record */ + { 0x0000fd19, 46 }, /* 3270_ChangeScreen */ + { 0x0000fd1a, 109 }, /* 3270_DeleteWord */ + { 0x0000fd1b, 181 }, /* 3270_ExSelect */ + { 0x0000fd1c, 91 }, /* 3270_CursorSelect */ + { 0x0000fd1d, 293 }, /* 3270_PrintScreen */ + { 0x0000fd1e, 140 }, /* 3270_Enter */ + { 0x0000fe01, 17781 }, /* ISO_Lock */ + { 0x0000fe02, 17664 }, /* ISO_Level2_Latch */ + { 0x0000fe03, 17714 }, /* ISO_Level3_Shift */ + { 0x0000fe04, 17681 }, /* ISO_Level3_Latch */ + { 0x0000fe05, 17698 }, /* ISO_Level3_Lock */ + { 0x0000fe06, 17569 }, /* ISO_Group_Latch */ + { 0x0000fe07, 17585 }, /* ISO_Group_Lock */ + { 0x0000fe08, 17826 }, /* ISO_Next_Group */ + { 0x0000fe09, 17841 }, /* ISO_Next_Group_Lock */ + { 0x0000fe0a, 17950 }, /* ISO_Prev_Group */ + { 0x0000fe0b, 17965 }, /* ISO_Prev_Group_Lock */ + { 0x0000fe0c, 17532 }, /* ISO_First_Group */ + { 0x0000fe0d, 17548 }, /* ISO_First_Group_Lock */ + { 0x0000fe0e, 17616 }, /* ISO_Last_Group */ + { 0x0000fe0f, 17631 }, /* ISO_Last_Group_Lock */ + { 0x0000fe11, 17764 }, /* ISO_Level5_Shift */ + { 0x0000fe12, 17731 }, /* ISO_Level5_Latch */ + { 0x0000fe13, 17748 }, /* ISO_Level5_Lock */ + { 0x0000fe20, 17651 }, /* ISO_Left_Tab */ + { 0x0000fe21, 17809 }, /* ISO_Move_Line_Up */ + { 0x0000fe22, 17790 }, /* ISO_Move_Line_Down */ + { 0x0000fe23, 17883 }, /* ISO_Partial_Line_Up */ + { 0x0000fe24, 17861 }, /* ISO_Partial_Line_Down */ + { 0x0000fe25, 17903 }, /* ISO_Partial_Space_Left */ + { 0x0000fe26, 17926 }, /* ISO_Partial_Space_Right */ + { 0x0000fe27, 18059 }, /* ISO_Set_Margin_Left */ + { 0x0000fe28, 18079 }, /* ISO_Set_Margin_Right */ + { 0x0000fe29, 18010 }, /* ISO_Release_Margin_Left */ + { 0x0000fe2a, 18034 }, /* ISO_Release_Margin_Right */ + { 0x0000fe2b, 17985 }, /* ISO_Release_Both_Margins */ + { 0x0000fe2c, 17470 }, /* ISO_Fast_Cursor_Left */ + { 0x0000fe2d, 17491 }, /* ISO_Fast_Cursor_Right */ + { 0x0000fe2e, 17513 }, /* ISO_Fast_Cursor_Up */ + { 0x0000fe2f, 17449 }, /* ISO_Fast_Cursor_Down */ + { 0x0000fe30, 17372 }, /* ISO_Continuous_Underline */ + { 0x0000fe31, 17397 }, /* ISO_Discontinuous_Underline */ + { 0x0000fe32, 17425 }, /* ISO_Emphasize */ + { 0x0000fe33, 17354 }, /* ISO_Center_Object */ + { 0x0000fe34, 17439 }, /* ISO_Enter */ + { 0x0000fe50, 10858 }, /* dead_grave */ + { 0x0000fe51, 10531 }, /* dead_acute */ + { 0x0000fe52, 10754 }, /* dead_circumflex */ + { 0x0000fe53, 11097 }, /* dead_tilde */ + { 0x0000fe54, 10980 }, /* dead_macron */ + { 0x0000fe55, 10700 }, /* dead_breve */ + { 0x0000fe56, 10455 }, /* dead_abovedot */ + { 0x0000fe57, 10795 }, /* dead_diaeresis */ + { 0x0000fe58, 10493 }, /* dead_abovering */ + { 0x0000fe59, 10810 }, /* dead_doubleacute */ + { 0x0000fe5a, 10730 }, /* dead_caron */ + { 0x0000fe5b, 10741 }, /* dead_cedilla */ + { 0x0000fe5c, 11006 }, /* dead_ogonek */ + { 0x0000fe5d, 10933 }, /* dead_iota */ + { 0x0000fe5e, 11122 }, /* dead_voiced_sound */ + { 0x0000fe5f, 11046 }, /* dead_semivoiced_sound */ + { 0x0000fe60, 10615 }, /* dead_belowdot */ + { 0x0000fe61, 10880 }, /* dead_hook */ + { 0x0000fe62, 10890 }, /* dead_horn */ + { 0x0000fe63, 11085 }, /* dead_stroke */ + { 0x0000fe64, 10439 }, /* dead_abovecomma */ + { 0x0000fe65, 10469 }, /* dead_abovereversedcomma */ + { 0x0000fe66, 10827 }, /* dead_doublegrave */ + { 0x0000fe67, 10646 }, /* dead_belowring */ + { 0x0000fe68, 10629 }, /* dead_belowmacron */ + { 0x0000fe69, 10558 }, /* dead_belowcircumflex */ + { 0x0000fe6a, 10661 }, /* dead_belowtilde */ + { 0x0000fe6b, 10542 }, /* dead_belowbreve */ + { 0x0000fe6c, 10595 }, /* dead_belowdiaeresis */ + { 0x0000fe6d, 10914 }, /* dead_invertedbreve */ + { 0x0000fe6e, 10579 }, /* dead_belowcomma */ + { 0x0000fe6f, 10770 }, /* dead_currency */ + { 0x0000fe70, 583 }, /* AccessX_Enable */ + { 0x0000fe71, 598 }, /* AccessX_Feedback_Enable */ + { 0x0000fe72, 22342 }, /* RepeatKeys_Enable */ + { 0x0000fe73, 23774 }, /* SlowKeys_Enable */ + { 0x0000fe74, 3564 }, /* BounceKeys_Enable */ + { 0x0000fe75, 23836 }, /* StickyKeys_Enable */ + { 0x0000fe76, 19782 }, /* MouseKeys_Enable */ + { 0x0000fe77, 19759 }, /* MouseKeys_Accel_Enable */ + { 0x0000fe78, 21332 }, /* Overlay1_Enable */ + { 0x0000fe79, 21348 }, /* Overlay2_Enable */ + { 0x0000fe7a, 3309 }, /* AudibleBell_Enable */ + { 0x0000fe80, 10425 }, /* dead_a */ + { 0x0000fe81, 10432 }, /* dead_A */ + { 0x0000fe82, 10844 }, /* dead_e */ + { 0x0000fe83, 10851 }, /* dead_E */ + { 0x0000fe84, 10900 }, /* dead_i */ + { 0x0000fe85, 10907 }, /* dead_I */ + { 0x0000fe86, 10992 }, /* dead_o */ + { 0x0000fe87, 10999 }, /* dead_O */ + { 0x0000fe88, 11108 }, /* dead_u */ + { 0x0000fe89, 11115 }, /* dead_U */ + { 0x0000fe8a, 11068 }, /* dead_small_schwa */ + { 0x0000fe8b, 10711 }, /* dead_capital_schwa */ + { 0x0000fe8c, 10869 }, /* dead_greek */ + { 0x0000fe90, 10967 }, /* dead_lowline */ + { 0x0000fe91, 10508 }, /* dead_aboveverticalline */ + { 0x0000fe92, 10677 }, /* dead_belowverticalline */ + { 0x0000fe93, 10943 }, /* dead_longsolidusoverlay */ + { 0x0000fea0, 8594 }, /* ch */ + { 0x0000fea1, 8597 }, /* Ch */ + { 0x0000fea2, 8600 }, /* CH */ + { 0x0000fea3, 8443 }, /* c_h */ + { 0x0000fea4, 8447 }, /* C_h */ + { 0x0000fea5, 8451 }, /* C_H */ + { 0x0000fed0, 12536 }, /* First_Virtual_Screen */ + { 0x0000fed1, 22080 }, /* Prev_Virtual_Screen */ + { 0x0000fed2, 20028 }, /* Next_Virtual_Screen */ + { 0x0000fed4, 19161 }, /* Last_Virtual_Screen */ + { 0x0000fed5, 24382 }, /* Terminate_Server */ + { 0x0000fee0, 21998 }, /* Pointer_Left */ + { 0x0000fee1, 22011 }, /* Pointer_Right */ + { 0x0000fee2, 22025 }, /* Pointer_Up */ + { 0x0000fee3, 21843 }, /* Pointer_Down */ + { 0x0000fee4, 22036 }, /* Pointer_UpLeft */ + { 0x0000fee5, 22051 }, /* Pointer_UpRight */ + { 0x0000fee6, 21856 }, /* Pointer_DownLeft */ + { 0x0000fee7, 21873 }, /* Pointer_DownRight */ + { 0x0000fee8, 21671 }, /* Pointer_Button_Dflt */ + { 0x0000fee9, 21591 }, /* Pointer_Button1 */ + { 0x0000feea, 21607 }, /* Pointer_Button2 */ + { 0x0000feeb, 21623 }, /* Pointer_Button3 */ + { 0x0000feec, 21639 }, /* Pointer_Button4 */ + { 0x0000feed, 21655 }, /* Pointer_Button5 */ + { 0x0000feee, 21781 }, /* Pointer_DblClick_Dflt */ + { 0x0000feef, 21691 }, /* Pointer_DblClick1 */ + { 0x0000fef0, 21709 }, /* Pointer_DblClick2 */ + { 0x0000fef1, 21727 }, /* Pointer_DblClick3 */ + { 0x0000fef2, 21745 }, /* Pointer_DblClick4 */ + { 0x0000fef3, 21763 }, /* Pointer_DblClick5 */ + { 0x0000fef4, 21961 }, /* Pointer_Drag_Dflt */ + { 0x0000fef5, 21891 }, /* Pointer_Drag1 */ + { 0x0000fef6, 21905 }, /* Pointer_Drag2 */ + { 0x0000fef7, 21919 }, /* Pointer_Drag3 */ + { 0x0000fef8, 21933 }, /* Pointer_Drag4 */ + { 0x0000fef9, 21979 }, /* Pointer_EnableKeys */ + { 0x0000fefa, 21572 }, /* Pointer_Accelerate */ + { 0x0000fefb, 21803 }, /* Pointer_DfltBtnNext */ + { 0x0000fefc, 21823 }, /* Pointer_DfltBtnPrev */ + { 0x0000fefd, 21947 }, /* Pointer_Drag5 */ + { 0x0000ff08, 3362 }, /* BackSpace */ + { 0x0000ff09, 24298 }, /* Tab */ + { 0x0000ff0a, 19434 }, /* Linefeed */ + { 0x0000ff0b, 8633 }, /* Clear */ + { 0x0000ff0d, 22366 }, /* Return */ + { 0x0000ff13, 21481 }, /* Pause */ + { 0x0000ff14, 22699 }, /* Scroll_Lock */ + { 0x0000ff15, 24279 }, /* Sys_Req */ + { 0x0000ff1b, 12057 }, /* Escape */ + { 0x0000ff20, 19811 }, /* Multi_key */ + { 0x0000ff21, 18745 }, /* Kanji */ + { 0x0000ff22, 19802 }, /* Muhenkan */ + { 0x0000ff23, 16614 }, /* Henkan_Mode */ + { 0x0000ff24, 22562 }, /* Romaji */ + { 0x0000ff25, 16635 }, /* Hiragana */ + { 0x0000ff26, 18770 }, /* Katakana */ + { 0x0000ff27, 16644 }, /* Hiragana_Katakana */ + { 0x0000ff28, 29161 }, /* Zenkaku */ + { 0x0000ff29, 16048 }, /* Hankaku */ + { 0x0000ff2a, 29169 }, /* Zenkaku_Hankaku */ + { 0x0000ff2b, 25752 }, /* Touroku */ + { 0x0000ff2c, 19698 }, /* Massyo */ + { 0x0000ff2d, 18351 }, /* Kana_Lock */ + { 0x0000ff2e, 18562 }, /* Kana_Shift */ + { 0x0000ff2f, 11779 }, /* Eisu_Shift */ + { 0x0000ff30, 11790 }, /* Eisu_toggle */ + { 0x0000ff31, 14392 }, /* Hangul */ + { 0x0000ff32, 15780 }, /* Hangul_Start */ + { 0x0000ff33, 14511 }, /* Hangul_End */ + { 0x0000ff34, 14542 }, /* Hangul_Hanja */ + { 0x0000ff35, 15128 }, /* Hangul_Jamo */ + { 0x0000ff36, 15625 }, /* Hangul_Romaja */ + { 0x0000ff37, 8654 }, /* Codeinput */ + { 0x0000ff38, 15140 }, /* Hangul_Jeonja */ + { 0x0000ff39, 14445 }, /* Hangul_Banja */ + { 0x0000ff3a, 15420 }, /* Hangul_PreHanja */ + { 0x0000ff3b, 15403 }, /* Hangul_PostHanja */ + { 0x0000ff3c, 23012 }, /* SingleCandidate */ + { 0x0000ff3d, 19821 }, /* MultipleCandidate */ + { 0x0000ff3e, 22100 }, /* PreviousCandidate */ + { 0x0000ff3f, 15674 }, /* Hangul_Special */ + { 0x0000ff50, 16662 }, /* Home */ + { 0x0000ff51, 19244 }, /* Left */ + { 0x0000ff52, 26384 }, /* Up */ + { 0x0000ff53, 22373 }, /* Right */ + { 0x0000ff54, 11327 }, /* Down */ + { 0x0000ff55, 22124 }, /* Prior */ + { 0x0000ff56, 20023 }, /* Next */ + { 0x0000ff57, 11936 }, /* End */ + { 0x0000ff58, 3404 }, /* Begin */ + { 0x0000ff60, 22727 }, /* Select */ + { 0x0000ff61, 22118 }, /* Print */ + { 0x0000ff62, 12117 }, /* Execute */ + { 0x0000ff63, 17284 }, /* Insert */ + { 0x0000ff65, 26357 }, /* Undo */ + { 0x0000ff66, 22326 }, /* Redo */ + { 0x0000ff67, 19705 }, /* Menu */ + { 0x0000ff68, 12531 }, /* Find */ + { 0x0000ff69, 8489 }, /* Cancel */ + { 0x0000ff6a, 16602 }, /* Help */ + { 0x0000ff6b, 8377 }, /* Break */ + { 0x0000ff7e, 19747 }, /* Mode_switch */ + { 0x0000ff7f, 20169 }, /* Num_Lock */ + { 0x0000ff80, 19074 }, /* KP_Space */ + { 0x0000ff89, 19095 }, /* KP_Tab */ + { 0x0000ff8d, 18931 }, /* KP_Enter */ + { 0x0000ff91, 18949 }, /* KP_F1 */ + { 0x0000ff92, 18955 }, /* KP_F2 */ + { 0x0000ff93, 18961 }, /* KP_F3 */ + { 0x0000ff94, 18967 }, /* KP_F4 */ + { 0x0000ff95, 18973 }, /* KP_Home */ + { 0x0000ff96, 18991 }, /* KP_Left */ + { 0x0000ff97, 19102 }, /* KP_Up */ + { 0x0000ff98, 19052 }, /* KP_Right */ + { 0x0000ff99, 18916 }, /* KP_Down */ + { 0x0000ff9a, 19043 }, /* KP_Prior */ + { 0x0000ff9b, 19011 }, /* KP_Next */ + { 0x0000ff9c, 18924 }, /* KP_End */ + { 0x0000ff9d, 18876 }, /* KP_Begin */ + { 0x0000ff9e, 18981 }, /* KP_Insert */ + { 0x0000ff9f, 18896 }, /* KP_Delete */ + { 0x0000ffaa, 18999 }, /* KP_Multiply */ + { 0x0000ffab, 18858 }, /* KP_Add */ + { 0x0000ffac, 19061 }, /* KP_Separator */ + { 0x0000ffad, 19083 }, /* KP_Subtract */ + { 0x0000ffae, 18885 }, /* KP_Decimal */ + { 0x0000ffaf, 18906 }, /* KP_Divide */ + { 0x0000ffb0, 18808 }, /* KP_0 */ + { 0x0000ffb1, 18813 }, /* KP_1 */ + { 0x0000ffb2, 18818 }, /* KP_2 */ + { 0x0000ffb3, 18823 }, /* KP_3 */ + { 0x0000ffb4, 18828 }, /* KP_4 */ + { 0x0000ffb5, 18833 }, /* KP_5 */ + { 0x0000ffb6, 18838 }, /* KP_6 */ + { 0x0000ffb7, 18843 }, /* KP_7 */ + { 0x0000ffb8, 18848 }, /* KP_8 */ + { 0x0000ffb9, 18853 }, /* KP_9 */ + { 0x0000ffbd, 18940 }, /* KP_Equal */ + { 0x0000ffbe, 12159 }, /* F1 */ + { 0x0000ffbf, 12202 }, /* F2 */ + { 0x0000ffc0, 12245 }, /* F3 */ + { 0x0000ffc1, 12272 }, /* F4 */ + { 0x0000ffc2, 12275 }, /* F5 */ + { 0x0000ffc3, 12278 }, /* F6 */ + { 0x0000ffc4, 12281 }, /* F7 */ + { 0x0000ffc5, 12284 }, /* F8 */ + { 0x0000ffc6, 12287 }, /* F9 */ + { 0x0000ffc7, 12162 }, /* F10 */ + { 0x0000ffc8, 12166 }, /* F11 */ + { 0x0000ffc9, 12170 }, /* F12 */ + { 0x0000ffca, 12174 }, /* F13 */ + { 0x0000ffcb, 12178 }, /* F14 */ + { 0x0000ffcc, 12182 }, /* F15 */ + { 0x0000ffcd, 12186 }, /* F16 */ + { 0x0000ffce, 12190 }, /* F17 */ + { 0x0000ffcf, 12194 }, /* F18 */ + { 0x0000ffd0, 12198 }, /* F19 */ + { 0x0000ffd1, 12205 }, /* F20 */ + { 0x0000ffd2, 12209 }, /* F21 */ + { 0x0000ffd3, 12213 }, /* F22 */ + { 0x0000ffd4, 12217 }, /* F23 */ + { 0x0000ffd5, 12221 }, /* F24 */ + { 0x0000ffd6, 12225 }, /* F25 */ + { 0x0000ffd7, 12229 }, /* F26 */ + { 0x0000ffd8, 12233 }, /* F27 */ + { 0x0000ffd9, 12237 }, /* F28 */ + { 0x0000ffda, 12241 }, /* F29 */ + { 0x0000ffdb, 12248 }, /* F30 */ + { 0x0000ffdc, 12252 }, /* F31 */ + { 0x0000ffdd, 12256 }, /* F32 */ + { 0x0000ffde, 12260 }, /* F33 */ + { 0x0000ffdf, 12264 }, /* F34 */ + { 0x0000ffe0, 12268 }, /* F35 */ + { 0x0000ffe1, 22946 }, /* Shift_L */ + { 0x0000ffe2, 22965 }, /* Shift_R */ + { 0x0000ffe3, 8697 }, /* Control_L */ + { 0x0000ffe4, 8707 }, /* Control_R */ + { 0x0000ffe5, 8496 }, /* Caps_Lock */ + { 0x0000ffe6, 22954 }, /* Shift_Lock */ + { 0x0000ffe7, 19710 }, /* Meta_L */ + { 0x0000ffe8, 19717 }, /* Meta_R */ + { 0x0000ffe9, 880 }, /* Alt_L */ + { 0x0000ffea, 886 }, /* Alt_R */ + { 0x0000ffeb, 24263 }, /* Super_L */ + { 0x0000ffec, 24271 }, /* Super_R */ + { 0x0000ffed, 17046 }, /* Hyper_L */ + { 0x0000ffee, 17054 }, /* Hyper_R */ + { 0x0000fff1, 3642 }, /* braille_dot_1 */ + { 0x0000fff2, 3671 }, /* braille_dot_2 */ + { 0x0000fff3, 3685 }, /* braille_dot_3 */ + { 0x0000fff4, 3699 }, /* braille_dot_4 */ + { 0x0000fff5, 3713 }, /* braille_dot_5 */ + { 0x0000fff6, 3727 }, /* braille_dot_6 */ + { 0x0000fff7, 3741 }, /* braille_dot_7 */ + { 0x0000fff8, 3755 }, /* braille_dot_8 */ + { 0x0000fff9, 3769 }, /* braille_dot_9 */ + { 0x0000fffa, 3656 }, /* braille_dot_10 */ + { 0x0000ffff, 11160 }, /* Delete */ + { 0x00ffffff, 26531 }, /* VoidSymbol */ + { 0x0100012c, 17117 }, /* Ibreve */ + { 0x0100012d, 17124 }, /* ibreve */ + { 0x01000174, 26563 }, /* Wcircumflex */ + { 0x01000175, 26575 }, /* wcircumflex */ + { 0x01000176, 29010 }, /* Ycircumflex */ + { 0x01000177, 29022 }, /* ycircumflex */ + { 0x0100018f, 22649 }, /* SCHWA */ + { 0x0100019f, 20218 }, /* Obarred */ + { 0x010001a0, 20553 }, /* Ohorn */ + { 0x010001a1, 20559 }, /* ohorn */ + { 0x010001af, 25997 }, /* Uhorn */ + { 0x010001b0, 26003 }, /* uhorn */ + { 0x010001b5, 29212 }, /* Zstroke */ + { 0x010001b6, 29220 }, /* zstroke */ + { 0x010001b7, 12147 }, /* EZH */ + { 0x010001d1, 20254 }, /* Ocaron */ + { 0x010001d2, 20261 }, /* ocaron */ + { 0x010001e6, 12703 }, /* Gcaron */ + { 0x010001e7, 12710 }, /* gcaron */ + { 0x01000259, 22655 }, /* schwa */ + { 0x01000275, 20226 }, /* obarred */ + { 0x01000292, 12151 }, /* ezh */ + { 0x01000492, 9236 }, /* Cyrillic_GHE_bar */ + { 0x01000493, 9253 }, /* Cyrillic_ghe_bar */ + { 0x01000496, 10274 }, /* Cyrillic_ZHE_descender */ + { 0x01000497, 10297 }, /* Cyrillic_zhe_descender */ + { 0x0100049a, 9528 }, /* Cyrillic_KA_descender */ + { 0x0100049b, 9550 }, /* Cyrillic_ka_descender */ + { 0x0100049c, 9572 }, /* Cyrillic_KA_vertstroke */ + { 0x0100049d, 9595 }, /* Cyrillic_ka_vertstroke */ + { 0x010004a2, 9118 }, /* Cyrillic_EN_descender */ + { 0x010004a3, 9140 }, /* Cyrillic_en_descender */ + { 0x010004ae, 10036 }, /* Cyrillic_U_straight */ + { 0x010004af, 10056 }, /* Cyrillic_u_straight */ + { 0x010004b0, 10076 }, /* Cyrillic_U_straight_bar */ + { 0x010004b1, 10100 }, /* Cyrillic_u_straight_bar */ + { 0x010004b2, 9294 }, /* Cyrillic_HA_descender */ + { 0x010004b3, 9316 }, /* Cyrillic_ha_descender */ + { 0x010004b6, 8854 }, /* Cyrillic_CHE_descender */ + { 0x010004b7, 8877 }, /* Cyrillic_che_descender */ + { 0x010004b8, 8900 }, /* Cyrillic_CHE_vertstroke */ + { 0x010004b9, 8924 }, /* Cyrillic_che_vertstroke */ + { 0x010004ba, 9832 }, /* Cyrillic_SHHA */ + { 0x010004bb, 9846 }, /* Cyrillic_shha */ + { 0x010004d8, 9746 }, /* Cyrillic_SCHWA */ + { 0x010004d9, 9761 }, /* Cyrillic_schwa */ + { 0x010004e2, 9396 }, /* Cyrillic_I_macron */ + { 0x010004e3, 9414 }, /* Cyrillic_i_macron */ + { 0x010004e8, 9692 }, /* Cyrillic_O_bar */ + { 0x010004e9, 9707 }, /* Cyrillic_o_bar */ + { 0x010004ee, 10000 }, /* Cyrillic_U_macron */ + { 0x010004ef, 10018 }, /* Cyrillic_u_macron */ + { 0x01000531, 2124 }, /* Armenian_AYB */ + { 0x01000532, 2150 }, /* Armenian_BEN */ + { 0x01000533, 2374 }, /* Armenian_GIM */ + { 0x01000534, 2215 }, /* Armenian_DA */ + { 0x01000535, 3164 }, /* Armenian_YECH */ + { 0x01000536, 3210 }, /* Armenian_ZA */ + { 0x01000537, 2265 }, /* Armenian_E */ + { 0x01000538, 2100 }, /* Armenian_AT */ + { 0x01000539, 2964 }, /* Armenian_TO */ + { 0x0100053a, 3234 }, /* Armenian_ZHE */ + { 0x0100053b, 2464 }, /* Armenian_INI */ + { 0x0100053c, 2611 }, /* Armenian_LYUN */ + { 0x0100053d, 2564 }, /* Armenian_KHE */ + { 0x0100053e, 2988 }, /* Armenian_TSA */ + { 0x0100053f, 2538 }, /* Armenian_KEN */ + { 0x01000540, 2424 }, /* Armenian_HO */ + { 0x01000541, 2239 }, /* Armenian_DZA */ + { 0x01000542, 2346 }, /* Armenian_GHAT */ + { 0x01000543, 2936 }, /* Armenian_TCHE */ + { 0x01000544, 2639 }, /* Armenian_MEN */ + { 0x01000545, 2400 }, /* Armenian_HI */ + { 0x01000546, 2665 }, /* Armenian_NU */ + { 0x01000547, 2894 }, /* Armenian_SHA */ + { 0x01000548, 3112 }, /* Armenian_VO */ + { 0x01000549, 2189 }, /* Armenian_CHA */ + { 0x0100054a, 2727 }, /* Armenian_PE */ + { 0x0100054b, 2490 }, /* Armenian_JE */ + { 0x0100054c, 2797 }, /* Armenian_RA */ + { 0x0100054d, 2845 }, /* Armenian_SE */ + { 0x0100054e, 3086 }, /* Armenian_VEV */ + { 0x0100054f, 3040 }, /* Armenian_TYUN */ + { 0x01000550, 2821 }, /* Armenian_RE */ + { 0x01000551, 3014 }, /* Armenian_TSO */ + { 0x01000552, 3136 }, /* Armenian_VYUN */ + { 0x01000553, 2751 }, /* Armenian_PYUR */ + { 0x01000554, 2514 }, /* Armenian_KE */ + { 0x01000555, 2689 }, /* Armenian_O */ + { 0x01000556, 2303 }, /* Armenian_FE */ + { 0x0100055a, 2080 }, /* Armenian_apostrophe */ + { 0x0100055b, 2048 }, /* Armenian_accent */ + { 0x0100055c, 2287 }, /* Armenian_exclam */ + { 0x0100055d, 2869 }, /* Armenian_separation_mark */ + { 0x0100055e, 2779 }, /* Armenian_question */ + { 0x01000561, 2137 }, /* Armenian_ayb */ + { 0x01000562, 2163 }, /* Armenian_ben */ + { 0x01000563, 2387 }, /* Armenian_gim */ + { 0x01000564, 2227 }, /* Armenian_da */ + { 0x01000565, 3178 }, /* Armenian_yech */ + { 0x01000566, 3222 }, /* Armenian_za */ + { 0x01000567, 2276 }, /* Armenian_e */ + { 0x01000568, 2112 }, /* Armenian_at */ + { 0x01000569, 2976 }, /* Armenian_to */ + { 0x0100056a, 3247 }, /* Armenian_zhe */ + { 0x0100056b, 2477 }, /* Armenian_ini */ + { 0x0100056c, 2625 }, /* Armenian_lyun */ + { 0x0100056d, 2577 }, /* Armenian_khe */ + { 0x0100056e, 3001 }, /* Armenian_tsa */ + { 0x0100056f, 2551 }, /* Armenian_ken */ + { 0x01000570, 2436 }, /* Armenian_ho */ + { 0x01000571, 2252 }, /* Armenian_dza */ + { 0x01000572, 2360 }, /* Armenian_ghat */ + { 0x01000573, 2950 }, /* Armenian_tche */ + { 0x01000574, 2652 }, /* Armenian_men */ + { 0x01000575, 2412 }, /* Armenian_hi */ + { 0x01000576, 2677 }, /* Armenian_nu */ + { 0x01000577, 2907 }, /* Armenian_sha */ + { 0x01000578, 3124 }, /* Armenian_vo */ + { 0x01000579, 2202 }, /* Armenian_cha */ + { 0x0100057a, 2739 }, /* Armenian_pe */ + { 0x0100057b, 2502 }, /* Armenian_je */ + { 0x0100057c, 2809 }, /* Armenian_ra */ + { 0x0100057d, 2857 }, /* Armenian_se */ + { 0x0100057e, 3099 }, /* Armenian_vev */ + { 0x0100057f, 3054 }, /* Armenian_tyun */ + { 0x01000580, 2833 }, /* Armenian_re */ + { 0x01000581, 3027 }, /* Armenian_tso */ + { 0x01000582, 3150 }, /* Armenian_vyun */ + { 0x01000583, 2765 }, /* Armenian_pyur */ + { 0x01000584, 2526 }, /* Armenian_ke */ + { 0x01000585, 2700 }, /* Armenian_o */ + { 0x01000586, 2315 }, /* Armenian_fe */ + { 0x01000587, 2590 }, /* Armenian_ligature_ew */ + { 0x01000589, 2327 }, /* Armenian_full_stop */ + { 0x0100058a, 2448 }, /* Armenian_hyphen */ + { 0x01000653, 1580 }, /* Arabic_madda_above */ + { 0x01000654, 1316 }, /* Arabic_hamza_above */ + { 0x01000655, 1335 }, /* Arabic_hamza_below */ + { 0x01000660, 966 }, /* Arabic_0 */ + { 0x01000661, 975 }, /* Arabic_1 */ + { 0x01000662, 984 }, /* Arabic_2 */ + { 0x01000663, 993 }, /* Arabic_3 */ + { 0x01000664, 1002 }, /* Arabic_4 */ + { 0x01000665, 1011 }, /* Arabic_5 */ + { 0x01000666, 1020 }, /* Arabic_6 */ + { 0x01000667, 1029 }, /* Arabic_7 */ + { 0x01000668, 1038 }, /* Arabic_8 */ + { 0x01000669, 1047 }, /* Arabic_9 */ + { 0x0100066a, 1672 }, /* Arabic_percent */ + { 0x01000670, 1821 }, /* Arabic_superscript_alef */ + { 0x01000679, 1951 }, /* Arabic_tteh */ + { 0x0100067e, 1661 }, /* Arabic_peh */ + { 0x01000686, 1885 }, /* Arabic_tcheh */ + { 0x01000688, 1173 }, /* Arabic_ddal */ + { 0x01000691, 1729 }, /* Arabic_rreh */ + { 0x01000698, 1493 }, /* Arabic_jeh */ + { 0x010006a4, 1963 }, /* Arabic_veh */ + { 0x010006a9, 1544 }, /* Arabic_keheh */ + { 0x010006af, 1258 }, /* Arabic_gaf */ + { 0x010006ba, 1642 }, /* Arabic_noon_ghunna */ + { 0x010006be, 1442 }, /* Arabic_heh_doachashmee */ + { 0x010006c1, 1465 }, /* Arabic_heh_goal */ + { 0x010006cc, 12390 }, /* Farsi_yeh */ + { 0x010006d2, 1996 }, /* Arabic_yeh_baree */ + { 0x010006d4, 1242 }, /* Arabic_fullstop */ + { 0x010006f0, 12310 }, /* Farsi_0 */ + { 0x010006f1, 12318 }, /* Farsi_1 */ + { 0x010006f2, 12326 }, /* Farsi_2 */ + { 0x010006f3, 12334 }, /* Farsi_3 */ + { 0x010006f4, 12342 }, /* Farsi_4 */ + { 0x010006f5, 12350 }, /* Farsi_5 */ + { 0x010006f6, 12358 }, /* Farsi_6 */ + { 0x010006f7, 12366 }, /* Farsi_7 */ + { 0x010006f8, 12374 }, /* Farsi_8 */ + { 0x010006f9, 12382 }, /* Farsi_9 */ + { 0x01000d82, 23484 }, /* Sinh_ng */ + { 0x01000d83, 23278 }, /* Sinh_h2 */ + { 0x01000d85, 23047 }, /* Sinh_a */ + { 0x01000d86, 23054 }, /* Sinh_aa */ + { 0x01000d87, 23071 }, /* Sinh_ae */ + { 0x01000d88, 23088 }, /* Sinh_aee */ + { 0x01000d89, 23294 }, /* Sinh_i */ + { 0x01000d8a, 23309 }, /* Sinh_ii */ + { 0x01000d8b, 23695 }, /* Sinh_u */ + { 0x01000d8c, 23710 }, /* Sinh_uu */ + { 0x01000d8d, 23594 }, /* Sinh_ri */ + { 0x01000d8e, 23602 }, /* Sinh_rii */ + { 0x01000d8f, 23403 }, /* Sinh_lu */ + { 0x01000d90, 23420 }, /* Sinh_luu */ + { 0x01000d91, 23221 }, /* Sinh_e */ + { 0x01000d92, 23236 }, /* Sinh_ee */ + { 0x01000d93, 23107 }, /* Sinh_ai */ + { 0x01000d94, 23537 }, /* Sinh_o */ + { 0x01000d95, 23552 }, /* Sinh_oo */ + { 0x01000d96, 23132 }, /* Sinh_au */ + { 0x01000d9a, 23353 }, /* Sinh_ka */ + { 0x01000d9b, 23361 }, /* Sinh_kha */ + { 0x01000d9c, 23261 }, /* Sinh_ga */ + { 0x01000d9d, 23269 }, /* Sinh_gha */ + { 0x01000d9e, 23492 }, /* Sinh_ng2 */ + { 0x01000d9f, 23501 }, /* Sinh_nga */ + { 0x01000da0, 23166 }, /* Sinh_ca */ + { 0x01000da1, 23174 }, /* Sinh_cha */ + { 0x01000da2, 23326 }, /* Sinh_ja */ + { 0x01000da3, 23334 }, /* Sinh_jha */ + { 0x01000da4, 23528 }, /* Sinh_nya */ + { 0x01000da5, 23343 }, /* Sinh_jnya */ + { 0x01000da6, 23510 }, /* Sinh_nja */ + { 0x01000da7, 23676 }, /* Sinh_tta */ + { 0x01000da8, 23685 }, /* Sinh_ttha */ + { 0x01000da9, 23183 }, /* Sinh_dda */ + { 0x01000daa, 23192 }, /* Sinh_ddha */ + { 0x01000dab, 23519 }, /* Sinh_nna */ + { 0x01000dac, 23464 }, /* Sinh_ndda */ + { 0x01000dad, 23657 }, /* Sinh_tha */ + { 0x01000dae, 23666 }, /* Sinh_thha */ + { 0x01000daf, 23202 }, /* Sinh_dha */ + { 0x01000db0, 23211 }, /* Sinh_dhha */ + { 0x01000db1, 23456 }, /* Sinh_na */ + { 0x01000db3, 23474 }, /* Sinh_ndha */ + { 0x01000db4, 23569 }, /* Sinh_pa */ + { 0x01000db5, 23577 }, /* Sinh_pha */ + { 0x01000db6, 23149 }, /* Sinh_ba */ + { 0x01000db7, 23157 }, /* Sinh_bha */ + { 0x01000db8, 23439 }, /* Sinh_ma */ + { 0x01000db9, 23447 }, /* Sinh_mba */ + { 0x01000dba, 23735 }, /* Sinh_ya */ + { 0x01000dbb, 23586 }, /* Sinh_ra */ + { 0x01000dbd, 23386 }, /* Sinh_la */ + { 0x01000dc0, 23727 }, /* Sinh_va */ + { 0x01000dc1, 23638 }, /* Sinh_sha */ + { 0x01000dc2, 23647 }, /* Sinh_ssha */ + { 0x01000dc3, 23630 }, /* Sinh_sa */ + { 0x01000dc4, 23286 }, /* Sinh_ha */ + { 0x01000dc5, 23394 }, /* Sinh_lla */ + { 0x01000dc6, 23253 }, /* Sinh_fa */ + { 0x01000dca, 23124 }, /* Sinh_al */ + { 0x01000dcf, 23062 }, /* Sinh_aa2 */ + { 0x01000dd0, 23079 }, /* Sinh_ae2 */ + { 0x01000dd1, 23097 }, /* Sinh_aee2 */ + { 0x01000dd2, 23301 }, /* Sinh_i2 */ + { 0x01000dd3, 23317 }, /* Sinh_ii2 */ + { 0x01000dd4, 23702 }, /* Sinh_u2 */ + { 0x01000dd6, 23718 }, /* Sinh_uu2 */ + { 0x01000dd8, 23611 }, /* Sinh_ru2 */ + { 0x01000dd9, 23228 }, /* Sinh_e2 */ + { 0x01000dda, 23244 }, /* Sinh_ee2 */ + { 0x01000ddb, 23115 }, /* Sinh_ai2 */ + { 0x01000ddc, 23544 }, /* Sinh_o2 */ + { 0x01000ddd, 23560 }, /* Sinh_oo2 */ + { 0x01000dde, 23140 }, /* Sinh_au2 */ + { 0x01000ddf, 23411 }, /* Sinh_lu2 */ + { 0x01000df2, 23620 }, /* Sinh_ruu2 */ + { 0x01000df3, 23429 }, /* Sinh_luu2 */ + { 0x01000df4, 23370 }, /* Sinh_kunddaliya */ + { 0x010010d0, 12759 }, /* Georgian_an */ + { 0x010010d1, 12771 }, /* Georgian_ban */ + { 0x010010d2, 12875 }, /* Georgian_gan */ + { 0x010010d3, 12838 }, /* Georgian_don */ + { 0x010010d4, 12851 }, /* Georgian_en */ + { 0x010010d5, 13201 }, /* Georgian_vin */ + { 0x010010d6, 13239 }, /* Georgian_zen */ + { 0x010010d7, 13163 }, /* Georgian_tan */ + { 0x010010d8, 12966 }, /* Georgian_in */ + { 0x010010d9, 13005 }, /* Georgian_kan */ + { 0x010010da, 13032 }, /* Georgian_las */ + { 0x010010db, 13045 }, /* Georgian_man */ + { 0x010010dc, 13058 }, /* Georgian_nar */ + { 0x010010dd, 13071 }, /* Georgian_on */ + { 0x010010de, 13083 }, /* Georgian_par */ + { 0x010010df, 13252 }, /* Georgian_zhar */ + { 0x010010e0, 13123 }, /* Georgian_rae */ + { 0x010010e1, 13136 }, /* Georgian_san */ + { 0x010010e2, 13176 }, /* Georgian_tar */ + { 0x010010e3, 13189 }, /* Georgian_un */ + { 0x010010e4, 13096 }, /* Georgian_phar */ + { 0x010010e5, 13018 }, /* Georgian_khar */ + { 0x010010e6, 12888 }, /* Georgian_ghan */ + { 0x010010e7, 13110 }, /* Georgian_qar */ + { 0x010010e8, 13149 }, /* Georgian_shin */ + { 0x010010e9, 12811 }, /* Georgian_chin */ + { 0x010010ea, 12784 }, /* Georgian_can */ + { 0x010010eb, 12992 }, /* Georgian_jil */ + { 0x010010ec, 12825 }, /* Georgian_cil */ + { 0x010010ed, 12797 }, /* Georgian_char */ + { 0x010010ee, 13226 }, /* Georgian_xan */ + { 0x010010ef, 12978 }, /* Georgian_jhan */ + { 0x010010f0, 12902 }, /* Georgian_hae */ + { 0x010010f1, 12928 }, /* Georgian_he */ + { 0x010010f2, 12940 }, /* Georgian_hie */ + { 0x010010f3, 13214 }, /* Georgian_we */ + { 0x010010f4, 12915 }, /* Georgian_har */ + { 0x010010f5, 12953 }, /* Georgian_hoe */ + { 0x010010f6, 12863 }, /* Georgian_fi */ + { 0x01001e02, 3332 }, /* Babovedot */ + { 0x01001e03, 3342 }, /* babovedot */ + { 0x01001e0a, 10324 }, /* Dabovedot */ + { 0x01001e0b, 10334 }, /* dabovedot */ + { 0x01001e1e, 12290 }, /* Fabovedot */ + { 0x01001e1f, 12300 }, /* fabovedot */ + { 0x01001e36, 19192 }, /* Lbelowdot */ + { 0x01001e37, 19202 }, /* lbelowdot */ + { 0x01001e40, 19537 }, /* Mabovedot */ + { 0x01001e41, 19547 }, /* mabovedot */ + { 0x01001e56, 21377 }, /* Pabovedot */ + { 0x01001e57, 21387 }, /* pabovedot */ + { 0x01001e60, 22583 }, /* Sabovedot */ + { 0x01001e61, 22593 }, /* sabovedot */ + { 0x01001e6a, 24302 }, /* Tabovedot */ + { 0x01001e6b, 24312 }, /* tabovedot */ + { 0x01001e80, 26609 }, /* Wgrave */ + { 0x01001e81, 26616 }, /* wgrave */ + { 0x01001e82, 26549 }, /* Wacute */ + { 0x01001e83, 26556 }, /* wacute */ + { 0x01001e84, 26587 }, /* Wdiaeresis */ + { 0x01001e85, 26598 }, /* wdiaeresis */ + { 0x01001e8a, 26635 }, /* Xabovedot */ + { 0x01001e8b, 26645 }, /* xabovedot */ + { 0x01001ea0, 416 }, /* Abelowdot */ + { 0x01001ea1, 426 }, /* abelowdot */ + { 0x01001ea2, 868 }, /* Ahook */ + { 0x01001ea3, 874 }, /* ahook */ + { 0x01001ea4, 646 }, /* Acircumflexacute */ + { 0x01001ea5, 663 }, /* acircumflexacute */ + { 0x01001ea6, 720 }, /* Acircumflexgrave */ + { 0x01001ea7, 737 }, /* acircumflexgrave */ + { 0x01001ea8, 754 }, /* Acircumflexhook */ + { 0x01001ea9, 770 }, /* acircumflexhook */ + { 0x01001eaa, 786 }, /* Acircumflextilde */ + { 0x01001eab, 803 }, /* acircumflextilde */ + { 0x01001eac, 680 }, /* Acircumflexbelowdot */ + { 0x01001ead, 700 }, /* acircumflexbelowdot */ + { 0x01001eae, 459 }, /* Abreveacute */ + { 0x01001eaf, 471 }, /* abreveacute */ + { 0x01001eb0, 513 }, /* Abrevegrave */ + { 0x01001eb1, 525 }, /* abrevegrave */ + { 0x01001eb2, 537 }, /* Abrevehook */ + { 0x01001eb3, 548 }, /* abrevehook */ + { 0x01001eb4, 559 }, /* Abrevetilde */ + { 0x01001eb5, 571 }, /* abrevetilde */ + { 0x01001eb6, 483 }, /* Abrevebelowdot */ + { 0x01001eb7, 498 }, /* abrevebelowdot */ + { 0x01001eb8, 11462 }, /* Ebelowdot */ + { 0x01001eb9, 11472 }, /* ebelowdot */ + { 0x01001eba, 11738 }, /* Ehook */ + { 0x01001ebb, 11744 }, /* ehook */ + { 0x01001ebc, 12076 }, /* Etilde */ + { 0x01001ebd, 12083 }, /* etilde */ + { 0x01001ebe, 11520 }, /* Ecircumflexacute */ + { 0x01001ebf, 11537 }, /* ecircumflexacute */ + { 0x01001ec0, 11594 }, /* Ecircumflexgrave */ + { 0x01001ec1, 11611 }, /* ecircumflexgrave */ + { 0x01001ec2, 11628 }, /* Ecircumflexhook */ + { 0x01001ec3, 11644 }, /* ecircumflexhook */ + { 0x01001ec4, 11660 }, /* Ecircumflextilde */ + { 0x01001ec5, 11677 }, /* ecircumflextilde */ + { 0x01001ec6, 11554 }, /* Ecircumflexbelowdot */ + { 0x01001ec7, 11574 }, /* ecircumflexbelowdot */ + { 0x01001ec8, 17219 }, /* Ihook */ + { 0x01001ec9, 17225 }, /* ihook */ + { 0x01001eca, 17097 }, /* Ibelowdot */ + { 0x01001ecb, 17107 }, /* ibelowdot */ + { 0x01001ecc, 20234 }, /* Obelowdot */ + { 0x01001ecd, 20244 }, /* obelowdot */ + { 0x01001ece, 20541 }, /* Ohook */ + { 0x01001ecf, 20547 }, /* ohook */ + { 0x01001ed0, 20292 }, /* Ocircumflexacute */ + { 0x01001ed1, 20309 }, /* ocircumflexacute */ + { 0x01001ed2, 20366 }, /* Ocircumflexgrave */ + { 0x01001ed3, 20383 }, /* ocircumflexgrave */ + { 0x01001ed4, 20400 }, /* Ocircumflexhook */ + { 0x01001ed5, 20416 }, /* ocircumflexhook */ + { 0x01001ed6, 20432 }, /* Ocircumflextilde */ + { 0x01001ed7, 20449 }, /* ocircumflextilde */ + { 0x01001ed8, 20326 }, /* Ocircumflexbelowdot */ + { 0x01001ed9, 20346 }, /* ocircumflexbelowdot */ + { 0x01001eda, 20565 }, /* Ohornacute */ + { 0x01001edb, 20576 }, /* ohornacute */ + { 0x01001edc, 20615 }, /* Ohorngrave */ + { 0x01001edd, 20626 }, /* ohorngrave */ + { 0x01001ede, 20637 }, /* Ohornhook */ + { 0x01001edf, 20647 }, /* ohornhook */ + { 0x01001ee0, 20657 }, /* Ohorntilde */ + { 0x01001ee1, 20668 }, /* ohorntilde */ + { 0x01001ee2, 20587 }, /* Ohornbelowdot */ + { 0x01001ee3, 20601 }, /* ohornbelowdot */ + { 0x01001ee4, 25865 }, /* Ubelowdot */ + { 0x01001ee5, 25875 }, /* ubelowdot */ + { 0x01001ee6, 25985 }, /* Uhook */ + { 0x01001ee7, 25991 }, /* uhook */ + { 0x01001ee8, 26009 }, /* Uhornacute */ + { 0x01001ee9, 26020 }, /* uhornacute */ + { 0x01001eea, 26059 }, /* Uhorngrave */ + { 0x01001eeb, 26070 }, /* uhorngrave */ + { 0x01001eec, 26081 }, /* Uhornhook */ + { 0x01001eed, 26091 }, /* uhornhook */ + { 0x01001eee, 26101 }, /* Uhorntilde */ + { 0x01001eef, 26112 }, /* uhorntilde */ + { 0x01001ef0, 26031 }, /* Uhornbelowdot */ + { 0x01001ef1, 26045 }, /* uhornbelowdot */ + { 0x01001ef2, 29060 }, /* Ygrave */ + { 0x01001ef3, 29067 }, /* ygrave */ + { 0x01001ef4, 28990 }, /* Ybelowdot */ + { 0x01001ef5, 29000 }, /* ybelowdot */ + { 0x01001ef6, 29074 }, /* Yhook */ + { 0x01001ef7, 29080 }, /* yhook */ + { 0x01001ef8, 29086 }, /* Ytilde */ + { 0x01001ef9, 29093 }, /* ytilde */ + { 0x01002070, 29199 }, /* zerosuperior */ + { 0x01002074, 12632 }, /* foursuperior */ + { 0x01002075, 12594 }, /* fivesuperior */ + { 0x01002076, 23756 }, /* sixsuperior */ + { 0x01002077, 22932 }, /* sevensuperior */ + { 0x01002078, 11765 }, /* eightsuperior */ + { 0x01002079, 20062 }, /* ninesuperior */ + { 0x01002080, 29185 }, /* zerosubscript */ + { 0x01002081, 20742 }, /* onesubscript */ + { 0x01002082, 25812 }, /* twosubscript */ + { 0x01002083, 25556 }, /* threesubscript */ + { 0x01002084, 12618 }, /* foursubscript */ + { 0x01002085, 12580 }, /* fivesubscript */ + { 0x01002086, 23743 }, /* sixsubscript */ + { 0x01002087, 22917 }, /* sevensubscript */ + { 0x01002088, 11750 }, /* eightsubscript */ + { 0x01002089, 20048 }, /* ninesubscript */ + { 0x010020a0, 11694 }, /* EcuSign */ + { 0x010020a1, 8670 }, /* ColonSign */ + { 0x010020a2, 8744 }, /* CruzeiroSign */ + { 0x010020a3, 12416 }, /* FFrancSign */ + { 0x010020a4, 19448 }, /* LiraSign */ + { 0x010020a5, 19724 }, /* MillSign */ + { 0x010020a6, 19967 }, /* NairaSign */ + { 0x010020a7, 21526 }, /* PesetaSign */ + { 0x010020a8, 22569 }, /* RupeeSign */ + { 0x010020a9, 26623 }, /* WonSign */ + { 0x010020aa, 20009 }, /* NewSheqelSign */ + { 0x010020ab, 11258 }, /* DongSign */ + { 0x01002202, 21446 }, /* partdifferential */ + { 0x01002205, 11919 }, /* emptyset */ + { 0x01002208, 11802 }, /* elementof */ + { 0x01002209, 20112 }, /* notelementof */ + { 0x0100220b, 8686 }, /* containsas */ + { 0x0100221a, 23809 }, /* squareroot */ + { 0x0100221b, 8757 }, /* cuberoot */ + { 0x0100221c, 12645 }, /* fourthroot */ + { 0x0100222c, 11232 }, /* dintegral */ + { 0x0100222d, 25585 }, /* tintegral */ + { 0x01002235, 3396 }, /* because */ + { 0x01002247, 20100 }, /* notapproxeq */ + { 0x01002248, 945 }, /* approxeq */ + { 0x01002262, 20134 }, /* notidentical */ + { 0x01002263, 23854 }, /* stricteq */ + { 0x01002800, 3628 }, /* braille_blank */ + { 0x01002801, 3783 }, /* braille_dots_1 */ + { 0x01002802, 6151 }, /* braille_dots_2 */ + { 0x01002803, 3798 }, /* braille_dots_12 */ + { 0x01002804, 7303 }, /* braille_dots_3 */ + { 0x01002805, 5014 }, /* braille_dots_13 */ + { 0x01002806, 6166 }, /* braille_dots_23 */ + { 0x01002807, 3814 }, /* braille_dots_123 */ + { 0x01002808, 7863 }, /* braille_dots_4 */ + { 0x01002809, 5606 }, /* braille_dots_14 */ + { 0x0100280a, 6758 }, /* braille_dots_24 */ + { 0x0100280b, 4438 }, /* braille_dots_124 */ + { 0x0100280c, 7318 }, /* braille_dots_34 */ + { 0x0100280d, 5030 }, /* braille_dots_134 */ + { 0x0100280e, 6182 }, /* braille_dots_234 */ + { 0x0100280f, 3831 }, /* braille_dots_1234 */ + { 0x01002810, 8135 }, /* braille_dots_5 */ + { 0x01002811, 5894 }, /* braille_dots_15 */ + { 0x01002812, 7046 }, /* braille_dots_25 */ + { 0x01002813, 4742 }, /* braille_dots_125 */ + { 0x01002814, 7606 }, /* braille_dots_35 */ + { 0x01002815, 5334 }, /* braille_dots_135 */ + { 0x01002816, 6486 }, /* braille_dots_235 */ + { 0x01002817, 4151 }, /* braille_dots_1235 */ + { 0x01002818, 7878 }, /* braille_dots_45 */ + { 0x01002819, 5622 }, /* braille_dots_145 */ + { 0x0100281a, 6774 }, /* braille_dots_245 */ + { 0x0100281b, 4455 }, /* braille_dots_1245 */ + { 0x0100281c, 7334 }, /* braille_dots_345 */ + { 0x0100281d, 5047 }, /* braille_dots_1345 */ + { 0x0100281e, 6199 }, /* braille_dots_2345 */ + { 0x0100281f, 3849 }, /* braille_dots_12345 */ + { 0x01002820, 8267 }, /* braille_dots_6 */ + { 0x01002821, 6034 }, /* braille_dots_16 */ + { 0x01002822, 7186 }, /* braille_dots_26 */ + { 0x01002823, 4890 }, /* braille_dots_126 */ + { 0x01002824, 7746 }, /* braille_dots_36 */ + { 0x01002825, 5482 }, /* braille_dots_136 */ + { 0x01002826, 6634 }, /* braille_dots_236 */ + { 0x01002827, 4307 }, /* braille_dots_1236 */ + { 0x01002828, 8018 }, /* braille_dots_46 */ + { 0x01002829, 5770 }, /* braille_dots_146 */ + { 0x0100282a, 6922 }, /* braille_dots_246 */ + { 0x0100282b, 4611 }, /* braille_dots_1246 */ + { 0x0100282c, 7482 }, /* braille_dots_346 */ + { 0x0100282d, 5203 }, /* braille_dots_1346 */ + { 0x0100282e, 6355 }, /* braille_dots_2346 */ + { 0x0100282f, 4013 }, /* braille_dots_12346 */ + { 0x01002830, 8150 }, /* braille_dots_56 */ + { 0x01002831, 5910 }, /* braille_dots_156 */ + { 0x01002832, 7062 }, /* braille_dots_256 */ + { 0x01002833, 4759 }, /* braille_dots_1256 */ + { 0x01002834, 7622 }, /* braille_dots_356 */ + { 0x01002835, 5351 }, /* braille_dots_1356 */ + { 0x01002836, 6503 }, /* braille_dots_2356 */ + { 0x01002837, 4169 }, /* braille_dots_12356 */ + { 0x01002838, 7894 }, /* braille_dots_456 */ + { 0x01002839, 5639 }, /* braille_dots_1456 */ + { 0x0100283a, 6791 }, /* braille_dots_2456 */ + { 0x0100283b, 4473 }, /* braille_dots_12456 */ + { 0x0100283c, 7351 }, /* braille_dots_3456 */ + { 0x0100283d, 5065 }, /* braille_dots_13456 */ + { 0x0100283e, 6217 }, /* braille_dots_23456 */ + { 0x0100283f, 3868 }, /* braille_dots_123456 */ + { 0x01002840, 8331 }, /* braille_dots_7 */ + { 0x01002841, 6102 }, /* braille_dots_17 */ + { 0x01002842, 7254 }, /* braille_dots_27 */ + { 0x01002843, 4962 }, /* braille_dots_127 */ + { 0x01002844, 7814 }, /* braille_dots_37 */ + { 0x01002845, 5554 }, /* braille_dots_137 */ + { 0x01002846, 6706 }, /* braille_dots_237 */ + { 0x01002847, 4383 }, /* braille_dots_1237 */ + { 0x01002848, 8086 }, /* braille_dots_47 */ + { 0x01002849, 5842 }, /* braille_dots_147 */ + { 0x0100284a, 6994 }, /* braille_dots_247 */ + { 0x0100284b, 4687 }, /* braille_dots_1247 */ + { 0x0100284c, 7554 }, /* braille_dots_347 */ + { 0x0100284d, 5279 }, /* braille_dots_1347 */ + { 0x0100284e, 6431 }, /* braille_dots_2347 */ + { 0x0100284f, 4093 }, /* braille_dots_12347 */ + { 0x01002850, 8218 }, /* braille_dots_57 */ + { 0x01002851, 5982 }, /* braille_dots_157 */ + { 0x01002852, 7134 }, /* braille_dots_257 */ + { 0x01002853, 4835 }, /* braille_dots_1257 */ + { 0x01002854, 7694 }, /* braille_dots_357 */ + { 0x01002855, 5427 }, /* braille_dots_1357 */ + { 0x01002856, 6579 }, /* braille_dots_2357 */ + { 0x01002857, 4249 }, /* braille_dots_12357 */ + { 0x01002858, 7966 }, /* braille_dots_457 */ + { 0x01002859, 5715 }, /* braille_dots_1457 */ + { 0x0100285a, 6867 }, /* braille_dots_2457 */ + { 0x0100285b, 4553 }, /* braille_dots_12457 */ + { 0x0100285c, 7427 }, /* braille_dots_3457 */ + { 0x0100285d, 5145 }, /* braille_dots_13457 */ + { 0x0100285e, 6297 }, /* braille_dots_23457 */ + { 0x0100285f, 3952 }, /* braille_dots_123457 */ + { 0x01002860, 8282 }, /* braille_dots_67 */ + { 0x01002861, 6050 }, /* braille_dots_167 */ + { 0x01002862, 7202 }, /* braille_dots_267 */ + { 0x01002863, 4907 }, /* braille_dots_1267 */ + { 0x01002864, 7762 }, /* braille_dots_367 */ + { 0x01002865, 5499 }, /* braille_dots_1367 */ + { 0x01002866, 6651 }, /* braille_dots_2367 */ + { 0x01002867, 4325 }, /* braille_dots_12367 */ + { 0x01002868, 8034 }, /* braille_dots_467 */ + { 0x01002869, 5787 }, /* braille_dots_1467 */ + { 0x0100286a, 6939 }, /* braille_dots_2467 */ + { 0x0100286b, 4629 }, /* braille_dots_12467 */ + { 0x0100286c, 7499 }, /* braille_dots_3467 */ + { 0x0100286d, 5221 }, /* braille_dots_13467 */ + { 0x0100286e, 6373 }, /* braille_dots_23467 */ + { 0x0100286f, 4032 }, /* braille_dots_123467 */ + { 0x01002870, 8166 }, /* braille_dots_567 */ + { 0x01002871, 5927 }, /* braille_dots_1567 */ + { 0x01002872, 7079 }, /* braille_dots_2567 */ + { 0x01002873, 4777 }, /* braille_dots_12567 */ + { 0x01002874, 7639 }, /* braille_dots_3567 */ + { 0x01002875, 5369 }, /* braille_dots_13567 */ + { 0x01002876, 6521 }, /* braille_dots_23567 */ + { 0x01002877, 4188 }, /* braille_dots_123567 */ + { 0x01002878, 7911 }, /* braille_dots_4567 */ + { 0x01002879, 5657 }, /* braille_dots_14567 */ + { 0x0100287a, 6809 }, /* braille_dots_24567 */ + { 0x0100287b, 4492 }, /* braille_dots_124567 */ + { 0x0100287c, 7369 }, /* braille_dots_34567 */ + { 0x0100287d, 5084 }, /* braille_dots_134567 */ + { 0x0100287e, 6236 }, /* braille_dots_234567 */ + { 0x0100287f, 3888 }, /* braille_dots_1234567 */ + { 0x01002880, 8362 }, /* braille_dots_8 */ + { 0x01002881, 6135 }, /* braille_dots_18 */ + { 0x01002882, 7287 }, /* braille_dots_28 */ + { 0x01002883, 4997 }, /* braille_dots_128 */ + { 0x01002884, 7847 }, /* braille_dots_38 */ + { 0x01002885, 5589 }, /* braille_dots_138 */ + { 0x01002886, 6741 }, /* braille_dots_238 */ + { 0x01002887, 4420 }, /* braille_dots_1238 */ + { 0x01002888, 8119 }, /* braille_dots_48 */ + { 0x01002889, 5877 }, /* braille_dots_148 */ + { 0x0100288a, 7029 }, /* braille_dots_248 */ + { 0x0100288b, 4724 }, /* braille_dots_1248 */ + { 0x0100288c, 7589 }, /* braille_dots_348 */ + { 0x0100288d, 5316 }, /* braille_dots_1348 */ + { 0x0100288e, 6468 }, /* braille_dots_2348 */ + { 0x0100288f, 4132 }, /* braille_dots_12348 */ + { 0x01002890, 8251 }, /* braille_dots_58 */ + { 0x01002891, 6017 }, /* braille_dots_158 */ + { 0x01002892, 7169 }, /* braille_dots_258 */ + { 0x01002893, 4872 }, /* braille_dots_1258 */ + { 0x01002894, 7729 }, /* braille_dots_358 */ + { 0x01002895, 5464 }, /* braille_dots_1358 */ + { 0x01002896, 6616 }, /* braille_dots_2358 */ + { 0x01002897, 4288 }, /* braille_dots_12358 */ + { 0x01002898, 8001 }, /* braille_dots_458 */ + { 0x01002899, 5752 }, /* braille_dots_1458 */ + { 0x0100289a, 6904 }, /* braille_dots_2458 */ + { 0x0100289b, 4592 }, /* braille_dots_12458 */ + { 0x0100289c, 7464 }, /* braille_dots_3458 */ + { 0x0100289d, 5184 }, /* braille_dots_13458 */ + { 0x0100289e, 6336 }, /* braille_dots_23458 */ + { 0x0100289f, 3993 }, /* braille_dots_123458 */ + { 0x010028a0, 8315 }, /* braille_dots_68 */ + { 0x010028a1, 6085 }, /* braille_dots_168 */ + { 0x010028a2, 7237 }, /* braille_dots_268 */ + { 0x010028a3, 4944 }, /* braille_dots_1268 */ + { 0x010028a4, 7797 }, /* braille_dots_368 */ + { 0x010028a5, 5536 }, /* braille_dots_1368 */ + { 0x010028a6, 6688 }, /* braille_dots_2368 */ + { 0x010028a7, 4364 }, /* braille_dots_12368 */ + { 0x010028a8, 8069 }, /* braille_dots_468 */ + { 0x010028a9, 5824 }, /* braille_dots_1468 */ + { 0x010028aa, 6976 }, /* braille_dots_2468 */ + { 0x010028ab, 4668 }, /* braille_dots_12468 */ + { 0x010028ac, 7536 }, /* braille_dots_3468 */ + { 0x010028ad, 5260 }, /* braille_dots_13468 */ + { 0x010028ae, 6412 }, /* braille_dots_23468 */ + { 0x010028af, 4073 }, /* braille_dots_123468 */ + { 0x010028b0, 8201 }, /* braille_dots_568 */ + { 0x010028b1, 5964 }, /* braille_dots_1568 */ + { 0x010028b2, 7116 }, /* braille_dots_2568 */ + { 0x010028b3, 4816 }, /* braille_dots_12568 */ + { 0x010028b4, 7676 }, /* braille_dots_3568 */ + { 0x010028b5, 5408 }, /* braille_dots_13568 */ + { 0x010028b6, 6560 }, /* braille_dots_23568 */ + { 0x010028b7, 4229 }, /* braille_dots_123568 */ + { 0x010028b8, 7948 }, /* braille_dots_4568 */ + { 0x010028b9, 5696 }, /* braille_dots_14568 */ + { 0x010028ba, 6848 }, /* braille_dots_24568 */ + { 0x010028bb, 4533 }, /* braille_dots_124568 */ + { 0x010028bc, 7408 }, /* braille_dots_34568 */ + { 0x010028bd, 5125 }, /* braille_dots_134568 */ + { 0x010028be, 6277 }, /* braille_dots_234568 */ + { 0x010028bf, 3931 }, /* braille_dots_1234568 */ + { 0x010028c0, 8346 }, /* braille_dots_78 */ + { 0x010028c1, 6118 }, /* braille_dots_178 */ + { 0x010028c2, 7270 }, /* braille_dots_278 */ + { 0x010028c3, 4979 }, /* braille_dots_1278 */ + { 0x010028c4, 7830 }, /* braille_dots_378 */ + { 0x010028c5, 5571 }, /* braille_dots_1378 */ + { 0x010028c6, 6723 }, /* braille_dots_2378 */ + { 0x010028c7, 4401 }, /* braille_dots_12378 */ + { 0x010028c8, 8102 }, /* braille_dots_478 */ + { 0x010028c9, 5859 }, /* braille_dots_1478 */ + { 0x010028ca, 7011 }, /* braille_dots_2478 */ + { 0x010028cb, 4705 }, /* braille_dots_12478 */ + { 0x010028cc, 7571 }, /* braille_dots_3478 */ + { 0x010028cd, 5297 }, /* braille_dots_13478 */ + { 0x010028ce, 6449 }, /* braille_dots_23478 */ + { 0x010028cf, 4112 }, /* braille_dots_123478 */ + { 0x010028d0, 8234 }, /* braille_dots_578 */ + { 0x010028d1, 5999 }, /* braille_dots_1578 */ + { 0x010028d2, 7151 }, /* braille_dots_2578 */ + { 0x010028d3, 4853 }, /* braille_dots_12578 */ + { 0x010028d4, 7711 }, /* braille_dots_3578 */ + { 0x010028d5, 5445 }, /* braille_dots_13578 */ + { 0x010028d6, 6597 }, /* braille_dots_23578 */ + { 0x010028d7, 4268 }, /* braille_dots_123578 */ + { 0x010028d8, 7983 }, /* braille_dots_4578 */ + { 0x010028d9, 5733 }, /* braille_dots_14578 */ + { 0x010028da, 6885 }, /* braille_dots_24578 */ + { 0x010028db, 4572 }, /* braille_dots_124578 */ + { 0x010028dc, 7445 }, /* braille_dots_34578 */ + { 0x010028dd, 5164 }, /* braille_dots_134578 */ + { 0x010028de, 6316 }, /* braille_dots_234578 */ + { 0x010028df, 3972 }, /* braille_dots_1234578 */ + { 0x010028e0, 8298 }, /* braille_dots_678 */ + { 0x010028e1, 6067 }, /* braille_dots_1678 */ + { 0x010028e2, 7219 }, /* braille_dots_2678 */ + { 0x010028e3, 4925 }, /* braille_dots_12678 */ + { 0x010028e4, 7779 }, /* braille_dots_3678 */ + { 0x010028e5, 5517 }, /* braille_dots_13678 */ + { 0x010028e6, 6669 }, /* braille_dots_23678 */ + { 0x010028e7, 4344 }, /* braille_dots_123678 */ + { 0x010028e8, 8051 }, /* braille_dots_4678 */ + { 0x010028e9, 5805 }, /* braille_dots_14678 */ + { 0x010028ea, 6957 }, /* braille_dots_24678 */ + { 0x010028eb, 4648 }, /* braille_dots_124678 */ + { 0x010028ec, 7517 }, /* braille_dots_34678 */ + { 0x010028ed, 5240 }, /* braille_dots_134678 */ + { 0x010028ee, 6392 }, /* braille_dots_234678 */ + { 0x010028ef, 4052 }, /* braille_dots_1234678 */ + { 0x010028f0, 8183 }, /* braille_dots_5678 */ + { 0x010028f1, 5945 }, /* braille_dots_15678 */ + { 0x010028f2, 7097 }, /* braille_dots_25678 */ + { 0x010028f3, 4796 }, /* braille_dots_125678 */ + { 0x010028f4, 7657 }, /* braille_dots_35678 */ + { 0x010028f5, 5388 }, /* braille_dots_135678 */ + { 0x010028f6, 6540 }, /* braille_dots_235678 */ + { 0x010028f7, 4208 }, /* braille_dots_1235678 */ + { 0x010028f8, 7929 }, /* braille_dots_45678 */ + { 0x010028f9, 5676 }, /* braille_dots_145678 */ + { 0x010028fa, 6828 }, /* braille_dots_245678 */ + { 0x010028fb, 4512 }, /* braille_dots_1245678 */ + { 0x010028fc, 7388 }, /* braille_dots_345678 */ + { 0x010028fd, 5104 }, /* braille_dots_1345678 */ + { 0x010028fe, 6256 }, /* braille_dots_2345678 */ + { 0x010028ff, 3909 }, /* braille_dots_12345678 */ + { 0x100000a8, 16910 }, /* hpmute_acute */ + { 0x100000a9, 16977 }, /* hpmute_grave */ + { 0x100000aa, 16923 }, /* hpmute_asciicircum */ + { 0x100000ab, 16960 }, /* hpmute_diaeresis */ + { 0x100000ac, 16942 }, /* hpmute_asciitilde */ + { 0x100000af, 16867 }, /* hplira */ + { 0x100000be, 16813 }, /* hpguilder */ + { 0x100000ee, 17014 }, /* hpYdiaeresis */ + { 0x100000f6, 16874 }, /* hplongminus */ + { 0x100000fc, 16767 }, /* hpblock */ + { 0x1000fe22, 10414 }, /* Ddiaeresis */ + { 0x1000fe27, 10344 }, /* Dacute_accent */ + { 0x1000fe2c, 10379 }, /* Dcedilla_accent */ + { 0x1000fe5e, 10395 }, /* Dcircumflex_accent */ + { 0x1000fe60, 11189 }, /* Dgrave_accent */ + { 0x1000fe7e, 11417 }, /* Dtilde */ + { 0x1000feb0, 11388 }, /* Dring_accent */ + { 0x1000ff00, 11380 }, /* DRemove */ + { 0x1000ff48, 16886 }, /* hpModelock1 */ + { 0x1000ff49, 16898 }, /* hpModelock2 */ + { 0x1000ff6c, 16990 }, /* hpReset */ + { 0x1000ff6d, 16998 }, /* hpSystem */ + { 0x1000ff6e, 17007 }, /* hpUser */ + { 0x1000ff6f, 16775 }, /* hpClearLine */ + { 0x1000ff70, 16836 }, /* hpInsertLine */ + { 0x1000ff71, 16800 }, /* hpDeleteLine */ + { 0x1000ff72, 16823 }, /* hpInsertChar */ + { 0x1000ff73, 16787 }, /* hpDeleteChar */ + { 0x1000ff74, 16757 }, /* hpBackTab */ + { 0x1000ff75, 16854 }, /* hpKP_BackTab */ + { 0x1000ff76, 12125 }, /* Ext16bit_L */ + { 0x1000ff77, 12136 }, /* Ext16bit_R */ + { 0x1004ff02, 20956 }, /* osfCopy */ + { 0x1004ff03, 20964 }, /* osfCut */ + { 0x1004ff04, 21163 }, /* osfPaste */ + { 0x1004ff07, 20900 }, /* osfBackTab */ + { 0x1004ff08, 20887 }, /* osfBackSpace */ + { 0x1004ff0b, 20947 }, /* osfClear */ + { 0x1004ff1b, 21026 }, /* osfEscape */ + { 0x1004ff31, 20876 }, /* osfAddMode */ + { 0x1004ff32, 21197 }, /* osfPrimaryPaste */ + { 0x1004ff33, 21213 }, /* osfQuickPaste */ + { 0x1004ff40, 21128 }, /* osfPageLeft */ + { 0x1004ff41, 21153 }, /* osfPageUp */ + { 0x1004ff42, 21116 }, /* osfPageDown */ + { 0x1004ff43, 21140 }, /* osfPageRight */ + { 0x1004ff44, 20864 }, /* osfActivate */ + { 0x1004ff45, 21080 }, /* osfMenuBar */ + { 0x1004ff51, 21064 }, /* osfLeft */ + { 0x1004ff52, 21290 }, /* osfUp */ + { 0x1004ff53, 21250 }, /* osfRight */ + { 0x1004ff54, 20996 }, /* osfDown */ + { 0x1004ff57, 21015 }, /* osfEndLine */ + { 0x1004ff58, 20924 }, /* osfBeginLine */ + { 0x1004ff59, 21004 }, /* osfEndData */ + { 0x1004ff5a, 20911 }, /* osfBeginData */ + { 0x1004ff5b, 21185 }, /* osfPrevMenu */ + { 0x1004ff5c, 21104 }, /* osfNextMenu */ + { 0x1004ff5d, 21172 }, /* osfPrevField */ + { 0x1004ff5e, 21091 }, /* osfNextField */ + { 0x1004ff60, 21259 }, /* osfSelect */ + { 0x1004ff63, 21054 }, /* osfInsert */ + { 0x1004ff65, 21282 }, /* osfUndo */ + { 0x1004ff67, 21072 }, /* osfMenu */ + { 0x1004ff69, 20937 }, /* osfCancel */ + { 0x1004ff6a, 21046 }, /* osfHelp */ + { 0x1004ff71, 21269 }, /* osfSelectAll */ + { 0x1004ff72, 20981 }, /* osfDeselectAll */ + { 0x1004ff73, 21227 }, /* osfReselect */ + { 0x1004ff74, 21036 }, /* osfExtend */ + { 0x1004ff78, 21239 }, /* osfRestore */ + { 0x1004ffff, 20971 }, /* osfDelete */ + { 0x1005ff00, 24032 }, /* SunFA_Grave */ + { 0x1005ff01, 24003 }, /* SunFA_Circum */ + { 0x1005ff02, 24044 }, /* SunFA_Tilde */ + { 0x1005ff03, 23977 }, /* SunFA_Acute */ + { 0x1005ff04, 24016 }, /* SunFA_Diaeresis */ + { 0x1005ff05, 23989 }, /* SunFA_Cedilla */ + { 0x1005ff10, 23963 }, /* SunF36 */ + { 0x1005ff11, 23970 }, /* SunF37 */ + { 0x1005ff60, 24180 }, /* SunSys_Req */ + { 0x1005ff70, 24163 }, /* SunProps */ + { 0x1005ff71, 24064 }, /* SunFront */ + { 0x1005ff72, 23948 }, /* SunCopy */ + { 0x1005ff73, 24073 }, /* SunOpen */ + { 0x1005ff74, 24103 }, /* SunPaste */ + { 0x1005ff75, 23956 }, /* SunCut */ + { 0x1005ff76, 24112 }, /* SunPowerSwitch */ + { 0x1005ff77, 23884 }, /* SunAudioLowerVolume */ + { 0x1005ff78, 23904 }, /* SunAudioMute */ + { 0x1005ff79, 23917 }, /* SunAudioRaiseVolume */ + { 0x1005ff7a, 24199 }, /* SunVideoDegauss */ + { 0x1005ff7b, 24215 }, /* SunVideoLowerBrightness */ + { 0x1005ff7c, 24239 }, /* SunVideoRaiseBrightness */ + { 0x1005ff7d, 24127 }, /* SunPowerSwitchShift */ + { 0x1008fe01, 28451 }, /* XF86Switch_VT_1 */ + { 0x1008fe02, 28518 }, /* XF86Switch_VT_2 */ + { 0x1008fe03, 28534 }, /* XF86Switch_VT_3 */ + { 0x1008fe04, 28550 }, /* XF86Switch_VT_4 */ + { 0x1008fe05, 28566 }, /* XF86Switch_VT_5 */ + { 0x1008fe06, 28582 }, /* XF86Switch_VT_6 */ + { 0x1008fe07, 28598 }, /* XF86Switch_VT_7 */ + { 0x1008fe08, 28614 }, /* XF86Switch_VT_8 */ + { 0x1008fe09, 28630 }, /* XF86Switch_VT_9 */ + { 0x1008fe0a, 28467 }, /* XF86Switch_VT_10 */ + { 0x1008fe0b, 28484 }, /* XF86Switch_VT_11 */ + { 0x1008fe0c, 28501 }, /* XF86Switch_VT_12 */ + { 0x1008fe20, 28777 }, /* XF86Ungrab */ + { 0x1008fe21, 27135 }, /* XF86ClearGrab */ + { 0x1008fe22, 27962 }, /* XF86Next_VMode */ + { 0x1008fe23, 28084 }, /* XF86Prev_VMode */ + { 0x1008fe24, 27742 }, /* XF86LogWindowTree */ + { 0x1008fe25, 27715 }, /* XF86LogGrabInfo */ + { 0x1008ff01, 27853 }, /* XF86ModeLock */ + { 0x1008ff02, 27888 }, /* XF86MonBrightnessUp */ + { 0x1008ff03, 27866 }, /* XF86MonBrightnessDown */ + { 0x1008ff04, 27491 }, /* XF86KbdLightOnOff */ + { 0x1008ff05, 27471 }, /* XF86KbdBrightnessUp */ + { 0x1008ff06, 27449 }, /* XF86KbdBrightnessDown */ + { 0x1008ff10, 28383 }, /* XF86Standby */ + { 0x1008ff11, 26749 }, /* XF86AudioLowerVolume */ + { 0x1008ff12, 26802 }, /* XF86AudioMute */ + { 0x1008ff13, 26873 }, /* XF86AudioRaiseVolume */ + { 0x1008ff14, 26845 }, /* XF86AudioPlay */ + { 0x1008ff15, 26962 }, /* XF86AudioStop */ + { 0x1008ff16, 26859 }, /* XF86AudioPrev */ + { 0x1008ff17, 26816 }, /* XF86AudioNext */ + { 0x1008ff18, 27412 }, /* XF86HomePage */ + { 0x1008ff19, 27760 }, /* XF86Mail */ + { 0x1008ff1a, 28395 }, /* XF86Start */ + { 0x1008ff1b, 28307 }, /* XF86Search */ + { 0x1008ff1c, 26914 }, /* XF86AudioRecord */ + { 0x1008ff1d, 27090 }, /* XF86Calculator */ + { 0x1008ff1e, 27808 }, /* XF86Memo */ + { 0x1008ff1f, 28681 }, /* XF86ToDoList */ + { 0x1008ff20, 27105 }, /* XF86Calendar */ + { 0x1008ff21, 28057 }, /* XF86PowerDown */ + { 0x1008ff22, 27173 }, /* XF86ContrastAdjust */ + { 0x1008ff23, 28177 }, /* XF86RockerUp */ + { 0x1008ff24, 28146 }, /* XF86RockerDown */ + { 0x1008ff25, 28161 }, /* XF86RockerEnter */ + { 0x1008ff26, 26985 }, /* XF86Back */ + { 0x1008ff27, 27317 }, /* XF86Forward */ + { 0x1008ff28, 28405 }, /* XF86Stop */ + { 0x1008ff29, 28113 }, /* XF86Refresh */ + { 0x1008ff2a, 28071 }, /* XF86PowerOff */ + { 0x1008ff2b, 28865 }, /* XF86WakeUp */ + { 0x1008ff2c, 27258 }, /* XF86Eject */ + { 0x1008ff2d, 28247 }, /* XF86ScreenSaver */ + { 0x1008ff2e, 28921 }, /* XF86WWW */ + { 0x1008ff2f, 28347 }, /* XF86Sleep */ + { 0x1008ff30, 27291 }, /* XF86Favorites */ + { 0x1008ff31, 26830 }, /* XF86AudioPause */ + { 0x1008ff32, 26770 }, /* XF86AudioMedia */ + { 0x1008ff33, 27918 }, /* XF86MyComputer */ + { 0x1008ff34, 28831 }, /* XF86VendorHome */ + { 0x1008ff35, 27701 }, /* XF86LightBulb */ + { 0x1008ff36, 28338 }, /* XF86Shop */ + { 0x1008ff37, 27400 }, /* XF86History */ + { 0x1008ff38, 28001 }, /* XF86OpenURL */ + { 0x1008ff39, 26655 }, /* XF86AddFavorite */ + { 0x1008ff3a, 27425 }, /* XF86HotLinks */ + { 0x1008ff3b, 27054 }, /* XF86BrightnessAdjust */ + { 0x1008ff3c, 27305 }, /* XF86Finance */ + { 0x1008ff3d, 27159 }, /* XF86Community */ + { 0x1008ff3e, 26946 }, /* XF86AudioRewind */ + { 0x1008ff3f, 26994 }, /* XF86BackForward */ + { 0x1008ff40, 27509 }, /* XF86Launch0 */ + { 0x1008ff41, 27521 }, /* XF86Launch1 */ + { 0x1008ff42, 27533 }, /* XF86Launch2 */ + { 0x1008ff43, 27545 }, /* XF86Launch3 */ + { 0x1008ff44, 27557 }, /* XF86Launch4 */ + { 0x1008ff45, 27569 }, /* XF86Launch5 */ + { 0x1008ff46, 27581 }, /* XF86Launch6 */ + { 0x1008ff47, 27593 }, /* XF86Launch7 */ + { 0x1008ff48, 27605 }, /* XF86Launch8 */ + { 0x1008ff49, 27617 }, /* XF86Launch9 */ + { 0x1008ff4a, 27629 }, /* XF86LaunchA */ + { 0x1008ff4b, 27641 }, /* XF86LaunchB */ + { 0x1008ff4c, 27653 }, /* XF86LaunchC */ + { 0x1008ff4d, 27665 }, /* XF86LaunchD */ + { 0x1008ff4e, 27677 }, /* XF86LaunchE */ + { 0x1008ff4f, 27689 }, /* XF86LaunchF */ + { 0x1008ff50, 26671 }, /* XF86ApplicationLeft */ + { 0x1008ff51, 26691 }, /* XF86ApplicationRight */ + { 0x1008ff52, 27045 }, /* XF86Book */ + { 0x1008ff53, 27118 }, /* XF86CD */ + { 0x1008ff54, 27075 }, /* XF86Calculater */ + { 0x1008ff55, 27125 }, /* XF86Clear */ + { 0x1008ff56, 27149 }, /* XF86Close */ + { 0x1008ff57, 27192 }, /* XF86Copy */ + { 0x1008ff58, 27201 }, /* XF86Cut */ + { 0x1008ff59, 27224 }, /* XF86Display */ + { 0x1008ff5a, 27250 }, /* XF86DOS */ + { 0x1008ff5b, 27236 }, /* XF86Documents */ + { 0x1008ff5c, 27268 }, /* XF86Excel */ + { 0x1008ff5d, 27278 }, /* XF86Explorer */ + { 0x1008ff5e, 27360 }, /* XF86Game */ + { 0x1008ff5f, 27369 }, /* XF86Go */ + { 0x1008ff60, 27438 }, /* XF86iTouch */ + { 0x1008ff61, 27731 }, /* XF86LogOff */ + { 0x1008ff62, 27785 }, /* XF86Market */ + { 0x1008ff63, 27796 }, /* XF86Meeting */ + { 0x1008ff65, 27817 }, /* XF86MenuKB */ + { 0x1008ff66, 27828 }, /* XF86MenuPB */ + { 0x1008ff67, 27933 }, /* XF86MySites */ + { 0x1008ff68, 27945 }, /* XF86New */ + { 0x1008ff69, 27953 }, /* XF86News */ + { 0x1008ff6a, 27977 }, /* XF86OfficeHome */ + { 0x1008ff6b, 27992 }, /* XF86Open */ + { 0x1008ff6c, 28013 }, /* XF86Option */ + { 0x1008ff6d, 28024 }, /* XF86Paste */ + { 0x1008ff6e, 28034 }, /* XF86Phone */ + { 0x1008ff70, 28099 }, /* XF86Q */ + { 0x1008ff72, 28136 }, /* XF86Reply */ + { 0x1008ff73, 28125 }, /* XF86Reload */ + { 0x1008ff74, 28190 }, /* XF86RotateWindows */ + { 0x1008ff75, 28223 }, /* XF86RotationPB */ + { 0x1008ff76, 28208 }, /* XF86RotationKB */ + { 0x1008ff77, 28238 }, /* XF86Save */ + { 0x1008ff78, 28294 }, /* XF86ScrollUp */ + { 0x1008ff79, 28279 }, /* XF86ScrollDown */ + { 0x1008ff7a, 28263 }, /* XF86ScrollClick */ + { 0x1008ff7b, 28329 }, /* XF86Send */ + { 0x1008ff7c, 28357 }, /* XF86Spell */ + { 0x1008ff7d, 28367 }, /* XF86SplitScreen */ + { 0x1008ff7e, 28427 }, /* XF86Support */ + { 0x1008ff7f, 28646 }, /* XF86TaskPane */ + { 0x1008ff80, 28659 }, /* XF86Terminal */ + { 0x1008ff81, 28694 }, /* XF86Tools */ + { 0x1008ff82, 28766 }, /* XF86Travel */ + { 0x1008ff84, 28812 }, /* XF86UserPB */ + { 0x1008ff85, 28788 }, /* XF86User1KB */ + { 0x1008ff86, 28800 }, /* XF86User2KB */ + { 0x1008ff87, 28846 }, /* XF86Video */ + { 0x1008ff88, 28887 }, /* XF86WheelButton */ + { 0x1008ff89, 28912 }, /* XF86Word */ + { 0x1008ff8a, 28929 }, /* XF86Xfer */ + { 0x1008ff8b, 28949 }, /* XF86ZoomIn */ + { 0x1008ff8c, 28960 }, /* XF86ZoomOut */ + { 0x1008ff8d, 26976 }, /* XF86Away */ + { 0x1008ff8e, 27839 }, /* XF86Messenger */ + { 0x1008ff8f, 28876 }, /* XF86WebCam */ + { 0x1008ff90, 27769 }, /* XF86MailForward */ + { 0x1008ff91, 28044 }, /* XF86Pictures */ + { 0x1008ff92, 27908 }, /* XF86Music */ + { 0x1008ff93, 27010 }, /* XF86Battery */ + { 0x1008ff94, 27031 }, /* XF86Bluetooth */ + { 0x1008ff95, 28903 }, /* XF86WLAN */ + { 0x1008ff96, 28823 }, /* XF86UWB */ + { 0x1008ff97, 26732 }, /* XF86AudioForward */ + { 0x1008ff98, 26930 }, /* XF86AudioRepeat */ + { 0x1008ff99, 26894 }, /* XF86AudioRandomPlay */ + { 0x1008ff9a, 28414 }, /* XF86Subtitle */ + { 0x1008ff9b, 26712 }, /* XF86AudioCycleTrack */ + { 0x1008ff9c, 27209 }, /* XF86CycleAngle */ + { 0x1008ff9d, 27329 }, /* XF86FrameBack */ + { 0x1008ff9e, 27343 }, /* XF86FrameForward */ + { 0x1008ff9f, 28672 }, /* XF86Time */ + { 0x1008ffa0, 28318 }, /* XF86Select */ + { 0x1008ffa1, 28856 }, /* XF86View */ + { 0x1008ffa2, 28704 }, /* XF86TopMenu */ + { 0x1008ffa3, 28105 }, /* XF86Red */ + { 0x1008ffa4, 27376 }, /* XF86Green */ + { 0x1008ffa5, 28938 }, /* XF86Yellow */ + { 0x1008ffa6, 27022 }, /* XF86Blue */ + { 0x1008ffa7, 28439 }, /* XF86Suspend */ + { 0x1008ffa8, 27386 }, /* XF86Hibernate */ + { 0x1008ffa9, 28747 }, /* XF86TouchpadToggle */ + { 0x1008ffb0, 28732 }, /* XF86TouchpadOn */ + { 0x1008ffb1, 28716 }, /* XF86TouchpadOff */ + { 0x1008ffb2, 26785 }, /* XF86AudioMicMute */ }; diff --git a/src/3rdparty/xkbcommon/src/state.c b/src/3rdparty/xkbcommon/src/state.c index ac4576f5b8..768d47c182 100644 --- a/src/3rdparty/xkbcommon/src/state.c +++ b/src/3rdparty/xkbcommon/src/state.c @@ -60,6 +60,7 @@ */ #include "keymap.h" +#include "keysym.h" struct xkb_filter { union xkb_action action; @@ -405,7 +406,6 @@ xkb_action_breaks_latch(const union xkb_action *action) case ACTION_TYPE_PTR_LOCK: case ACTION_TYPE_CTRL_SET: case ACTION_TYPE_CTRL_LOCK: - case ACTION_TYPE_KEY_REDIRECT: case ACTION_TYPE_SWITCH_VT: case ACTION_TYPE_TERMINATE: return true; @@ -833,13 +833,26 @@ XKB_EXPORT xkb_keysym_t xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc) { const xkb_keysym_t *syms; + xkb_keysym_t sym; int num_syms; + xkb_mod_index_t caps; num_syms = xkb_state_key_get_syms(state, kc, &syms); if (num_syms != 1) return XKB_KEY_NoSymbol; - return syms[0]; + sym = syms[0]; + + /* + * Perform capitalization transformation, see: + * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier + */ + caps = xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CAPS); + if (xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0 && + xkb_state_mod_index_is_consumed(state, kc, caps) == 0) + sym = xkb_keysym_to_upper(sym); + + return sym; } /** @@ -989,13 +1002,12 @@ xkb_state_mod_names_are_active(struct xkb_state *state, { va_list ap; xkb_mod_index_t idx = 0; - const char *str; xkb_mod_mask_t wanted = 0; int ret = 0; va_start(ap, match); while (1) { - str = va_arg(ap, const char *); + const char *str = va_arg(ap, const char *); if (str == NULL) break; idx = xkb_keymap_mod_get_index(state->keymap, str); diff --git a/src/3rdparty/xkbcommon/src/text.c b/src/3rdparty/xkbcommon/src/text.c index 4b8ad0984f..59d6c775cb 100644 --- a/src/3rdparty/xkbcommon/src/text.c +++ b/src/3rdparty/xkbcommon/src/text.c @@ -175,10 +175,10 @@ const LookupEntry actionTypeNames[] = { { "SwitchScreen", ACTION_TYPE_SWITCH_VT }, { "SetControls", ACTION_TYPE_CTRL_SET }, { "LockControls", ACTION_TYPE_CTRL_LOCK }, - { "RedirectKey", ACTION_TYPE_KEY_REDIRECT }, - { "Redirect", ACTION_TYPE_KEY_REDIRECT }, { "Private", ACTION_TYPE_PRIVATE }, /* deprecated actions below here - unused */ + { "RedirectKey", ACTION_TYPE_NONE }, + { "Redirect", ACTION_TYPE_NONE }, { "ISOLock", ACTION_TYPE_NONE }, { "ActionMessage", ACTION_TYPE_NONE }, { "MessageAction", ACTION_TYPE_NONE }, @@ -251,9 +251,9 @@ const char * KeyNameText(struct xkb_context *ctx, xkb_atom_t name) { const char *sname = xkb_atom_text(ctx, name); - size_t len = strlen(sname) + 3; + size_t len = strlen_safe(sname) + 3; char *buf = xkb_context_get_buffer(ctx, len); - snprintf(buf, len, "<%s>", sname); + snprintf(buf, len, "<%s>", strempty(sname)); return buf; } diff --git a/src/3rdparty/xkbcommon/src/utils.c b/src/3rdparty/xkbcommon/src/utils.c new file mode 100644 index 0000000000..a00b04eeec --- /dev/null +++ b/src/3rdparty/xkbcommon/src/utils.c @@ -0,0 +1,107 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "utils.h" + +#ifdef HAVE_MMAP + +#include +#include +#include +#include +#include + +bool +map_file(FILE *file, const char **string_out, size_t *size_out) +{ + struct stat stat_buf; + const int fd = fileno(file); + char *string; + + /* Make sure to keep the errno on failure! */ + + if (fstat(fd, &stat_buf) != 0) + return false; + + string = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (string == MAP_FAILED) + return false; + + *string_out = string; + *size_out = stat_buf.st_size; + return true; +} + +void +unmap_file(const char *str, size_t size) +{ + munmap(UNCONSTIFY(str), size); +} + +#else + +bool +map_file(FILE *file, const char **string_out, size_t *size_out) +{ + long ret; + size_t ret_s; + char *string; + size_t size; + + /* Make sure to keep the errno on failure! */ + + ret = fseek(file, 0, SEEK_END); + if (ret != 0) + return false; + + ret = ftell(file); + if (ret < 0) + return false; + size = (size_t) ret; + + ret = fseek(file, 0, SEEK_SET); + if (ret < 0) + return false; + + string = malloc(size); + if (!string) + return false; + + ret_s = fread(string, 1, size, file); + if (ret_s < size) { + free(string); + return false; + } + + *string_out = string; + *size_out = size; + return true; +} + +void +unmap_file(const char *str, size_t size) +{ + free(UNCONSTIFY(str)); +} + +#endif diff --git a/src/3rdparty/xkbcommon/src/utils.h b/src/3rdparty/xkbcommon/src/utils.h index b4daaddaaa..81d1cc9412 100644 --- a/src/3rdparty/xkbcommon/src/utils.h +++ b/src/3rdparty/xkbcommon/src/utils.h @@ -24,8 +24,10 @@ #ifndef UTILS_H #define UTILS_H 1 +#include #include #include +#include #include #include @@ -70,6 +72,12 @@ strdup_safe(const char *s) return s ? strdup(s) : NULL; } +static inline size_t +strlen_safe(const char *s) +{ + return s ? strlen(s) : 0; +} + static inline bool isempty(const char *s) { @@ -82,6 +90,12 @@ strnull(const char *s) return s ? s : "(null)"; } +static inline const char * +strempty(const char *s) +{ + return s ? s : ""; +} + static inline void * memdup(const void *mem, size_t nmemb, size_t size) { @@ -91,6 +105,81 @@ memdup(const void *mem, size_t nmemb, size_t size) return p; } +static inline int +min(int misc, int other) +{ + return (misc < other) ? misc : other; +} + +static inline int +max(int misc, int other) +{ + return (misc > other) ? misc : other; +} + +/* ctype.h is locale-dependent and has other oddities. */ +static inline bool +is_space(char ch) +{ + return ch == ' ' || (ch >= '\t' && ch <= '\r'); +} + +static inline bool +is_alpha(char ch) +{ + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); +} + +static inline bool +is_digit(char ch) +{ + return ch >= '0' && ch <= '9'; +} + +static inline bool +is_alnum(char ch) +{ + return is_alpha(ch) || is_digit(ch); +} + +static inline bool +is_xdigit(char ch) +{ + return + (ch >= '0' && ch <= '9') || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); +} + +static inline bool +is_graph(char ch) +{ + /* See table in ascii(7). */ + return ch >= '!' && ch <= '~'; +} + +/* + * Return the bit position of the most significant bit. + * Note: this is 1-based! It's more useful this way, and returns 0 when + * mask is all 0s. + */ +static inline int +msb_pos(uint32_t mask) +{ + int pos = 0; + while (mask) { + pos++; + mask >>= 1; + } + return pos; +} + +bool +map_file(FILE *file, const char **string_out, size_t *size_out); + +void +unmap_file(const char *str, size_t size); + #define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr)))) #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -133,4 +222,10 @@ memdup(const void *mem, size_t nmemb, size_t size) # define ATTR_NULL_SENTINEL #endif /* GNUC >= 4 */ +#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 295) +#define ATTR_PACKED __attribute__((__packed__)) +#else +#define ATTR_PACKED +#endif + #endif /* UTILS_H */ diff --git a/src/3rdparty/xkbcommon/src/x11/util.c b/src/3rdparty/xkbcommon/src/x11/util.c new file mode 100644 index 0000000000..92ff2e630e --- /dev/null +++ b/src/3rdparty/xkbcommon/src/x11/util.c @@ -0,0 +1,215 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "x11-priv.h" + +XKB_EXPORT int +xkb_x11_setup_xkb_extension(xcb_connection_t *conn, + uint16_t major_xkb_version, + uint16_t minor_xkb_version, + enum xkb_x11_setup_xkb_extension_flags flags, + uint16_t *major_xkb_version_out, + uint16_t *minor_xkb_version_out, + uint8_t *base_event_out, + uint8_t *base_error_out) +{ + uint8_t base_event, base_error; + uint16_t server_major, server_minor; + + if (flags & ~(XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS)) { + /* log_err_func(ctx, "unrecognized flags: %#x\n", flags); */ + return 0; + } + + { + const xcb_query_extension_reply_t *reply = + xcb_get_extension_data(conn, &xcb_xkb_id); + if (!reply) { + /* log_err_func(ctx, "failed to query for XKB extension\n"); */ + return 0; + } + + if (!reply->present) { + /* log_err_func(ctx, "failed to start using XKB extension: not available in server\n"); */ + return 0; + } + + base_event = reply->first_event; + base_error = reply->first_error; + } + + { + xcb_generic_error_t *error = NULL; + xcb_xkb_use_extension_cookie_t cookie = + xcb_xkb_use_extension(conn, major_xkb_version, minor_xkb_version); + xcb_xkb_use_extension_reply_t *reply = + xcb_xkb_use_extension_reply(conn, cookie, &error); + + if (!reply) { + /* log_err_func(ctx, */ + /* "failed to start using XKB extension: error code %d\n", */ + /* error ? error->error_code : -1); */ + free(error); + return 0; + } + + if (!reply->supported) { + /* log_err_func(ctx, */ + /* "failed to start using XKB extension: server doesn't support version %d.%d\n", */ + /* major_xkb_version, minor_xkb_version); */ + free(reply); + return 0; + } + + server_major = reply->serverMajor; + server_minor = reply->serverMinor; + + free(reply); + } + + /* + * The XkbUseExtension() in libX11 has a *bunch* of legacy stuff, but + * it doesn't seem like any of it is useful to us. + */ + + if (major_xkb_version_out) + *major_xkb_version_out = server_major; + if (minor_xkb_version_out) + *minor_xkb_version_out = server_minor; + if (base_event_out) + *base_event_out = base_event; + if (base_error_out) + *base_error_out = base_error; + + return 1; +} + +XKB_EXPORT int32_t +xkb_x11_get_core_keyboard_device_id(xcb_connection_t *conn) +{ + int32_t device_id; + xcb_xkb_get_device_info_cookie_t cookie = + xcb_xkb_get_device_info(conn, XCB_XKB_ID_USE_CORE_KBD, + 0, 0, 0, 0, 0, 0); + xcb_xkb_get_device_info_reply_t *reply = + xcb_xkb_get_device_info_reply(conn, cookie, NULL); + + if (!reply) + return -1; + + device_id = reply->deviceID; + free(reply); + return device_id; +} + +bool +get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out) +{ + xcb_get_atom_name_cookie_t cookie; + xcb_get_atom_name_reply_t *reply; + int length; + char *name; + + if (atom == 0) { + *out = NULL; + return true; + } + + cookie = xcb_get_atom_name(conn, atom); + reply = xcb_get_atom_name_reply(conn, cookie, NULL); + if (!reply) + return false; + + length = xcb_get_atom_name_name_length(reply); + name = xcb_get_atom_name_name(reply); + + *out = strndup(name, length); + if (!*out) { + free(reply); + return false; + } + + free(reply); + return true; +} + +bool +adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn, + const xcb_atom_t *from, xkb_atom_t *to, const size_t count) +{ + enum { SIZE = 128 }; + xcb_get_atom_name_cookie_t cookies[SIZE]; + + /* Send and collect the atoms in batches of reasonable SIZE. */ + for (size_t batch = 0; batch <= count / SIZE; batch++) { + const size_t start = batch * SIZE; + const size_t stop = min((batch + 1) * SIZE, count); + + /* Send. */ + for (size_t i = start; i < stop; i++) + if (from[i] != XCB_ATOM_NONE) + cookies[i % SIZE] = xcb_get_atom_name(conn, from[i]); + + /* Collect. */ + for (size_t i = start; i < stop; i++) { + xcb_get_atom_name_reply_t *reply; + + if (from[i] == XCB_ATOM_NONE) { + to[i] = XKB_ATOM_NONE; + continue; + } + + reply = xcb_get_atom_name_reply(conn, cookies[i % SIZE], NULL); + if (!reply) + goto err_discard; + + to[i] = xkb_atom_intern(ctx, + xcb_get_atom_name_name(reply), + xcb_get_atom_name_name_length(reply)); + free(reply); + + if (to[i] == XKB_ATOM_NONE) + goto err_discard; + + continue; + + /* + * If we don't discard the uncollected replies, they just + * sit there waiting. Sad. + */ +err_discard: + for (size_t j = i + 1; j < stop; j++) + xcb_discard_reply(conn, cookies[j].sequence); + return false; + } + } + + return true; +} + +bool +adopt_atom(struct xkb_context *ctx, xcb_connection_t *conn, xcb_atom_t atom, + xkb_atom_t *out) +{ + return adopt_atoms(ctx, conn, &atom, out, 1); +} diff --git a/src/3rdparty/xkbcommon/src/x11/x11-keymap.c b/src/3rdparty/xkbcommon/src/x11/x11-keymap.c new file mode 100644 index 0000000000..968f187621 --- /dev/null +++ b/src/3rdparty/xkbcommon/src/x11/x11-keymap.c @@ -0,0 +1,1146 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "x11-priv.h" + +/* + * References for the lonesome traveler: + * Xkb protocol specification: + * http://www.x.org/releases/current/doc/kbproto/xkbproto.html + * The XCB xkb XML protocol file: + * /user/share/xcb/xkb.xml + * The XCB xkb header file: + * /usr/include/xcb/xkb.h + * The old kbproto header files: + * /usr/include/X11/extensions/XKB{,proto,str}.h + * Xlib XKB source code: + * /src/xkb/XKBGetMap.c (and friends) + * X server XKB protocol handling: + * /xkb/xkb.c + * Man pages: + * XkbGetMap(3), XkbGetCompatMap(3), etc. + */ + +/* Constants from /usr/include/X11/extensions/XKB.h */ +/* XkbNumModifiers. */ +#define NUM_REAL_MODS 8 +/* XkbNumVirtualMods. */ +#define NUM_VMODS 16 +/* XkbNoModifier. */ +#define NO_MODIFIER 0xff +/* XkbNumIndicators. */ +#define NUM_INDICATORS 32 +/* XkbAllIndicatorsMask. */ +#define ALL_INDICATORS_MASK 0xffffffff + +/* Some macros. Not very nice but it'd be worse without them. */ + +/* + * We try not to trust the server too much and be paranoid. If we get + * something which we definitely shouldn't, we fail. + */ +#define STRINGIFY(expr) #expr +#define FAIL_UNLESS(expr) do { \ + if (!(expr)) { \ + log_err(keymap->ctx, \ + "x11: failed to get keymap from X server: unmet condition in %s(): %s\n", \ + __func__, STRINGIFY(expr)); \ + goto fail; \ + } \ +} while (0) + +#define FAIL_IF_BAD_REPLY(reply, request_name) do { \ + if (!reply) { \ + log_err(keymap->ctx, \ + "x11: failed to get keymap from X server: %s request failed\n", \ + (request_name)); \ + goto fail; \ + } \ +} while (0) + +#define ALLOC_OR_FAIL(arr, nmemb) do { \ + if ((nmemb) > 0) { \ + (arr) = calloc((nmemb), sizeof(*(arr))); \ + if (!(arr)) \ + goto fail; \ + } \ +} while (0) + + +static xkb_mod_mask_t +translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high) +{ + /* We represent mod masks in a single uint32_t value, with real mods + * first and vmods after (though we don't make these distinctions). */ + return rmods | (vmods_low << 8) | (vmods_high << 16); +} + +static enum xkb_action_controls +translate_controls_mask(uint16_t wire) +{ + enum xkb_action_controls ret = 0; + if (wire & XCB_XKB_BOOL_CTRL_REPEAT_KEYS) + ret |= CONTROL_REPEAT; + if (wire & XCB_XKB_BOOL_CTRL_SLOW_KEYS) + ret |= CONTROL_SLOW; + if (wire & XCB_XKB_BOOL_CTRL_BOUNCE_KEYS) + ret |= CONTROL_DEBOUNCE; + if (wire & XCB_XKB_BOOL_CTRL_STICKY_KEYS) + ret |= CONTROL_STICKY; + if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS) + ret |= CONTROL_MOUSEKEYS; + if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS_ACCEL) + ret |= CONTROL_MOUSEKEYS_ACCEL; + if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_KEYS) + ret |= CONTROL_AX; + if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_TIMEOUT_MASK) + ret |= CONTROL_AX_TIMEOUT; + if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_FEEDBACK_MASK) + ret |= CONTROL_AX_FEEDBACK; + if (wire & XCB_XKB_BOOL_CTRL_AUDIBLE_BELL_MASK) + ret |= CONTROL_BELL; + if (wire & XCB_XKB_BOOL_CTRL_IGNORE_GROUP_LOCK_MASK) + ret |= CONTROL_IGNORE_GROUP_LOCK; + /* Some controls are not supported and don't appear here. */ + return ret; +} + +static void +translate_action(union xkb_action *action, const xcb_xkb_action_t *wire) +{ + switch (wire->type) { + case XCB_XKB_SA_TYPE_SET_MODS: + action->type = ACTION_TYPE_MOD_SET; + + action->mods.mods.mods = translate_mods(wire->setmods.realMods, + wire->setmods.vmodsLow, + wire->setmods.vmodsHigh); + action->mods.mods.mask = translate_mods(wire->setmods.mask, 0, 0); + + if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS) + action->mods.flags |= ACTION_LOCK_CLEAR; + if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) + action->mods.flags |= ACTION_LATCH_TO_LOCK; + if (wire->setmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) + action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; + + break; + case XCB_XKB_SA_TYPE_LATCH_MODS: + action->type = ACTION_TYPE_MOD_LATCH; + + action->mods.mods.mods = translate_mods(wire->latchmods.realMods, + wire->latchmods.vmodsLow, + wire->latchmods.vmodsHigh); + action->mods.mods.mask = translate_mods(wire->latchmods.mask, 0, 0); + + if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS) + action->mods.flags |= ACTION_LOCK_CLEAR; + if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) + action->mods.flags |= ACTION_LATCH_TO_LOCK; + if (wire->latchmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) + action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; + + break; + case XCB_XKB_SA_TYPE_LOCK_MODS: + action->type = ACTION_TYPE_MOD_LOCK; + + action->mods.mods.mods = translate_mods(wire->lockmods.realMods, + wire->lockmods.vmodsLow, + wire->lockmods.vmodsHigh); + action->mods.mods.mask = translate_mods(wire->lockmods.mask, 0, 0); + + if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK) + action->mods.flags |= ACTION_LOCK_NO_LOCK; + if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK) + action->mods.flags |= ACTION_LOCK_NO_UNLOCK; + if (wire->lockmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) + action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; + + break; + case XCB_XKB_SA_TYPE_SET_GROUP: + action->type = ACTION_TYPE_GROUP_SET; + + action->group.group = wire->setgroup.group; + + if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS) + action->group.flags |= ACTION_LOCK_CLEAR; + if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) + action->group.flags |= ACTION_LATCH_TO_LOCK; + if (wire->setmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) + action->group.flags |= ACTION_ABSOLUTE_SWITCH; + + break; + case XCB_XKB_SA_TYPE_LATCH_GROUP: + action->type = ACTION_TYPE_GROUP_LATCH; + + action->group.group = wire->latchgroup.group; + + if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS) + action->group.flags |= ACTION_LOCK_CLEAR; + if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) + action->group.flags |= ACTION_LATCH_TO_LOCK; + if (wire->latchmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) + action->group.flags |= ACTION_ABSOLUTE_SWITCH; + + break; + case XCB_XKB_SA_TYPE_LOCK_GROUP: + action->type = ACTION_TYPE_GROUP_LOCK; + + action->group.group = wire->lockgroup.group; + + if (wire->lockgroup.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) + action->group.flags |= ACTION_ABSOLUTE_SWITCH; + + break; + case XCB_XKB_SA_TYPE_MOVE_PTR: + action->type = ACTION_TYPE_PTR_MOVE; + + action->ptr.x = (wire->moveptr.xLow | (wire->moveptr.xHigh << 8)); + action->ptr.y = (wire->moveptr.yLow | (wire->moveptr.yHigh << 8)); + + if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION) + action->ptr.flags |= ACTION_NO_ACCEL; + if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_X) + action->ptr.flags |= ACTION_ABSOLUTE_X; + if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_Y) + action->ptr.flags |= ACTION_ABSOLUTE_Y; + + break; + case XCB_XKB_SA_TYPE_PTR_BTN: + action->type = ACTION_TYPE_PTR_BUTTON; + + action->btn.count = wire->ptrbtn.count; + action->btn.button = wire->ptrbtn.button; + action->btn.flags = 0; + + break; + case XCB_XKB_SA_TYPE_LOCK_PTR_BTN: + action->type = ACTION_TYPE_PTR_LOCK; + + action->btn.button = wire->lockptrbtn.button; + + if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK) + action->btn.flags |= ACTION_LOCK_NO_LOCK; + if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK) + action->btn.flags |= ACTION_LOCK_NO_UNLOCK; + + break; + case XCB_XKB_SA_TYPE_SET_PTR_DFLT: + action->type = ACTION_TYPE_PTR_DEFAULT; + + action->dflt.value = wire->setptrdflt.value; + + if (wire->setptrdflt.flags & XCB_XKB_SA_SET_PTR_DFLT_FLAG_DFLT_BTN_ABSOLUTE) + action->dflt.flags |= ACTION_ABSOLUTE_SWITCH; + + break; + case XCB_XKB_SA_TYPE_TERMINATE: + action->type = ACTION_TYPE_TERMINATE; + + break; + case XCB_XKB_SA_TYPE_SWITCH_SCREEN: + action->type = ACTION_TYPE_SWITCH_VT; + + action->screen.screen = wire->switchscreen.newScreen; + + if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION) + action->screen.flags |= ACTION_SAME_SCREEN; + if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_ABSOLUTE) + action->screen.flags |= ACTION_ABSOLUTE_SWITCH; + + break; + case XCB_XKB_SA_TYPE_SET_CONTROLS: + action->type = ACTION_TYPE_CTRL_SET; + { + const uint16_t mask = (wire->setcontrols.boolCtrlsLow | + (wire->setcontrols.boolCtrlsHigh << 8)); + action->ctrls.ctrls = translate_controls_mask(mask); + } + break; + case XCB_XKB_SA_TYPE_LOCK_CONTROLS: + action->type = ACTION_TYPE_CTRL_LOCK; + { + const uint16_t mask = (wire->lockcontrols.boolCtrlsLow | + (wire->lockcontrols.boolCtrlsHigh << 8)); + action->ctrls.ctrls = translate_controls_mask(mask); + } + break; + + case XCB_XKB_SA_TYPE_NO_ACTION: + /* We don't support these. */ + case XCB_XKB_SA_TYPE_ISO_LOCK: + case XCB_XKB_SA_TYPE_REDIRECT_KEY: + case XCB_XKB_SA_TYPE_ACTION_MESSAGE: + case XCB_XKB_SA_TYPE_DEVICE_BTN: + case XCB_XKB_SA_TYPE_LOCK_DEVICE_BTN: + case XCB_XKB_SA_TYPE_DEVICE_VALUATOR: + action->type = ACTION_TYPE_NONE; + break; + } +} + +static bool +get_types(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + int types_length = xcb_xkb_get_map_map_types_rtrn_length(reply, map); + xcb_xkb_key_type_iterator_t types_iter = + xcb_xkb_get_map_map_types_rtrn_iterator(reply, map); + + FAIL_UNLESS(reply->firstType == 0); + + keymap->num_types = reply->nTypes; + ALLOC_OR_FAIL(keymap->types, keymap->num_types); + + for (int i = 0; i < types_length; i++) { + xcb_xkb_key_type_t *wire_type = types_iter.data; + struct xkb_key_type *type = &keymap->types[i]; + + FAIL_UNLESS(wire_type->numLevels > 0); + + type->mods.mods = translate_mods(wire_type->mods_mods, + wire_type->mods_vmods, 0); + type->mods.mask = translate_mods(wire_type->mods_mask, 0, 0); + type->num_levels = wire_type->numLevels; + + { + int entries_length = xcb_xkb_key_type_map_length(wire_type); + xcb_xkb_kt_map_entry_iterator_t entries_iter = + xcb_xkb_key_type_map_iterator(wire_type); + + type->num_entries = wire_type->nMapEntries; + ALLOC_OR_FAIL(type->entries, type->num_entries); + + for (int j = 0; j < entries_length; j++) { + xcb_xkb_kt_map_entry_t *wire_entry = entries_iter.data; + struct xkb_key_type_entry *entry = &type->entries[j]; + + FAIL_UNLESS(wire_entry->level < type->num_levels); + + entry->level = wire_entry->level; + entry->mods.mods = translate_mods(wire_entry->mods_mods, + wire_entry->mods_vmods, 0); + entry->mods.mask = translate_mods(wire_entry->mods_mask, 0, 0); + + xcb_xkb_kt_map_entry_next(&entries_iter); + } + } + + { + int preserves_length = xcb_xkb_key_type_preserve_length(wire_type); + xcb_xkb_mod_def_iterator_t preserves_iter = + xcb_xkb_key_type_preserve_iterator(wire_type); + + FAIL_UNLESS(preserves_length <= type->num_entries); + + for (int j = 0; j < preserves_length; j++) { + xcb_xkb_mod_def_t *wire_preserve = preserves_iter.data; + struct xkb_key_type_entry *entry = &type->entries[j]; + + entry->preserve.mods = translate_mods(wire_preserve->realMods, + wire_preserve->vmods, 0); + entry->preserve.mask = translate_mods(wire_preserve->mask, 0, 0); + + xcb_xkb_mod_def_next(&preserves_iter); + } + } + + xcb_xkb_key_type_next(&types_iter); + } + + return true; + +fail: + return false; +} + +static bool +get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + int sym_maps_length = xcb_xkb_get_map_map_syms_rtrn_length(reply, map); + xcb_xkb_key_sym_map_iterator_t sym_maps_iter = + xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map); + + FAIL_UNLESS(reply->minKeyCode <= reply->maxKeyCode); + FAIL_UNLESS(reply->firstKeySym >= reply->minKeyCode); + FAIL_UNLESS(reply->firstKeySym + reply->nKeySyms <= reply->maxKeyCode + 1); + + keymap->min_key_code = reply->minKeyCode; + keymap->max_key_code = reply->maxKeyCode; + + ALLOC_OR_FAIL(keymap->keys, keymap->max_key_code + 1); + + for (xkb_keycode_t kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++) + keymap->keys[kc].keycode = kc; + + for (int i = 0; i < sym_maps_length; i++) { + xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data; + struct xkb_key *key = &keymap->keys[reply->firstKeySym + i]; + + key->num_groups = wire_sym_map->groupInfo & 0x0f; + FAIL_UNLESS(key->num_groups <= ARRAY_SIZE(wire_sym_map->kt_index)); + ALLOC_OR_FAIL(key->groups, key->num_groups); + + for (int j = 0; j < key->num_groups; j++) { + FAIL_UNLESS(wire_sym_map->kt_index[j] < keymap->num_types); + key->groups[j].type = &keymap->types[wire_sym_map->kt_index[j]]; + + ALLOC_OR_FAIL(key->groups[j].levels, key->groups[j].type->num_levels); + } + + key->out_of_range_group_number = (wire_sym_map->groupInfo & 0x30) >> 4; + + FAIL_UNLESS(key->out_of_range_group_number <= key->num_groups); + + if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_CLAMP_INTO_RANGE) + key->out_of_range_group_action = RANGE_SATURATE; + else if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_REDIRECT_INTO_RANGE) + key->out_of_range_group_action = RANGE_REDIRECT; + else + key->out_of_range_group_action = RANGE_WRAP; + + { + int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map); + xcb_keysym_t *syms_iter = xcb_xkb_key_sym_map_syms(wire_sym_map); + + FAIL_UNLESS(syms_length == wire_sym_map->width * key->num_groups); + + for (int j = 0; j < syms_length; j++) { + xcb_keysym_t wire_keysym = *syms_iter; + const xkb_layout_index_t group = j / wire_sym_map->width; + const xkb_level_index_t level = j % wire_sym_map->width; + + if (level < key->groups[group].type->num_levels && + wire_keysym != XKB_KEY_NoSymbol) { + key->groups[group].levels[level].num_syms = 1; + key->groups[group].levels[level].u.sym = wire_keysym; + } + + syms_iter++; + } + } + + xcb_xkb_key_sym_map_next(&sym_maps_iter); + } + + return true; + +fail: + return false; +} + +static bool +get_actions(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + int acts_count_length = + xcb_xkb_get_map_map_acts_rtrn_count_length(reply, map); + uint8_t *acts_count_iter = xcb_xkb_get_map_map_acts_rtrn_count(map); + xcb_xkb_action_iterator_t acts_iter = + xcb_xkb_get_map_map_acts_rtrn_acts_iterator(reply, map); + xcb_xkb_key_sym_map_iterator_t sym_maps_iter = + xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map); + + FAIL_UNLESS(reply->firstKeyAction == keymap->min_key_code); + FAIL_UNLESS(reply->firstKeyAction + reply->nKeyActions == + keymap->max_key_code + 1); + + for (int i = 0; i < acts_count_length; i++) { + xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data; + uint8_t wire_count = *acts_count_iter; + struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i]; + + for (int j = 0; j < wire_count; j++) { + xcb_xkb_action_t *wire_action = acts_iter.data; + const xkb_layout_index_t group = j / wire_sym_map->width; + const xkb_level_index_t level = j % wire_sym_map->width; + + if (level < key->groups[group].type->num_levels) { + union xkb_action *action = + &key->groups[group].levels[level].action; + + translate_action(action, wire_action); + } + + xcb_xkb_action_next(&acts_iter); + } + + acts_count_iter++; + xcb_xkb_key_sym_map_next(&sym_maps_iter); + } + + return true; + +fail: + return false; +} + +static bool +get_vmods(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map); + + darray_resize0(keymap->mods, + NUM_REAL_MODS + msb_pos(reply->virtualMods)); + + for (int i = 0; i < NUM_VMODS; i++) { + if (reply->virtualMods & (1 << i)) { + uint8_t wire = *iter; + struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i); + + mod->type = MOD_VIRT; + mod->mapping = translate_mods(wire, 0, 0); + + iter++; + } + } + + return true; +} + +static bool +get_explicits(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + int length = xcb_xkb_get_map_map_explicit_rtrn_length(reply, map); + xcb_xkb_set_explicit_iterator_t iter = + xcb_xkb_get_map_map_explicit_rtrn_iterator(reply, map); + + for (int i = 0; i < length; i++) { + xcb_xkb_set_explicit_t *wire = iter.data; + struct xkb_key *key = &keymap->keys[wire->keycode]; + + FAIL_UNLESS(wire->keycode >= keymap->min_key_code && + wire->keycode <= keymap->max_key_code); + + if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_1) && + key->num_groups > 0) + key->groups[0].explicit_type = true; + if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_2) && + key->num_groups > 1) + key->groups[1].explicit_type = true; + if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_3) && + key->num_groups > 2) + key->groups[2].explicit_type = true; + if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_4) && + key->num_groups > 3) + key->groups[3].explicit_type = true; + if (wire->explicit & XCB_XKB_EXPLICIT_INTERPRET) + key->explicit |= EXPLICIT_INTERP; + if (wire->explicit & XCB_XKB_EXPLICIT_AUTO_REPEAT) + key->explicit |= EXPLICIT_REPEAT; + if (wire->explicit & XCB_XKB_EXPLICIT_V_MOD_MAP) + key->explicit |= EXPLICIT_VMODMAP; + + xcb_xkb_set_explicit_next(&iter); + } + + return true; + +fail: + return false; +} + +static bool +get_modmaps(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + int length = xcb_xkb_get_map_map_modmap_rtrn_length(reply, map); + xcb_xkb_key_mod_map_iterator_t iter = + xcb_xkb_get_map_map_modmap_rtrn_iterator(reply, map); + + for (int i = 0; i < length; i++) { + xcb_xkb_key_mod_map_t *wire = iter.data; + struct xkb_key *key = &keymap->keys[wire->keycode]; + + FAIL_UNLESS(wire->keycode >= keymap->min_key_code && + wire->keycode <= keymap->max_key_code); + + key->modmap = wire->mods; + + xcb_xkb_key_mod_map_next(&iter); + } + + return true; + +fail: + return false; +} + +static bool +get_vmodmaps(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) +{ + int length = xcb_xkb_get_map_map_vmodmap_rtrn_length(reply, map); + xcb_xkb_key_v_mod_map_iterator_t iter = + xcb_xkb_get_map_map_vmodmap_rtrn_iterator(reply, map); + + for (int i = 0; i < length; i++) { + xcb_xkb_key_v_mod_map_t *wire = iter.data; + struct xkb_key *key = &keymap->keys[wire->keycode]; + + FAIL_UNLESS(wire->keycode >= keymap->min_key_code && + wire->keycode <= keymap->max_key_code); + + key->vmodmap = translate_mods(0, wire->vmods, 0); + + xcb_xkb_key_v_mod_map_next(&iter); + } + + return true; + +fail: + return false; +} + +static bool +get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, uint16_t device_id) +{ + static const xcb_xkb_map_part_t required_components = + (XCB_XKB_MAP_PART_KEY_TYPES | + XCB_XKB_MAP_PART_KEY_SYMS | + XCB_XKB_MAP_PART_MODIFIER_MAP | + XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | + XCB_XKB_MAP_PART_KEY_ACTIONS | + XCB_XKB_MAP_PART_VIRTUAL_MODS | + XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); + + xcb_xkb_get_map_cookie_t cookie = + xcb_xkb_get_map(conn, device_id, required_components, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + xcb_xkb_get_map_reply_t *reply = xcb_xkb_get_map_reply(conn, cookie, NULL); + xcb_xkb_get_map_map_t map; + + FAIL_IF_BAD_REPLY(reply, "XkbGetMap"); + + if ((reply->present & required_components) != required_components) + goto fail; + + xcb_xkb_get_map_map_unpack(xcb_xkb_get_map_map(reply), + reply->nTypes, + reply->nKeySyms, + reply->nKeyActions, + reply->totalActions, + reply->totalKeyBehaviors, + reply->virtualMods, + reply->totalKeyExplicit, + reply->totalModMapKeys, + reply->totalVModMapKeys, + reply->present, + &map); + + if (!get_types(keymap, conn, reply, &map) || + !get_sym_maps(keymap, conn, reply, &map) || + !get_actions(keymap, conn, reply, &map) || + !get_vmods(keymap, conn, reply, &map) || + !get_explicits(keymap, conn, reply, &map) || + !get_modmaps(keymap, conn, reply, &map) || + !get_vmodmaps(keymap, conn, reply, &map)) + goto fail; + + free(reply); + return true; + +fail: + free(reply); + return false; +} + +static bool +get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_indicator_map_reply_t *reply) +{ + xcb_xkb_indicator_map_iterator_t iter = + xcb_xkb_get_indicator_map_maps_iterator(reply); + + darray_resize0(keymap->leds, msb_pos(reply->which)); + + for (int i = 0; i < NUM_INDICATORS; i++) { + if (reply->which & (1 << i)) { + xcb_xkb_indicator_map_t *wire = iter.data; + struct xkb_led *led = &darray_item(keymap->leds, i); + + if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_BASE) + led->which_groups |= XKB_STATE_LAYOUT_DEPRESSED; + if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LATCHED) + led->which_groups |= XKB_STATE_LAYOUT_LATCHED; + if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LOCKED) + led->which_groups |= XKB_STATE_LAYOUT_LOCKED; + if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_EFFECTIVE) + led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE; + if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_COMPAT) + led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE; + + led->groups = wire->groups; + + if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_BASE) + led->which_mods |= XKB_STATE_MODS_DEPRESSED; + if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LATCHED) + led->which_mods |= XKB_STATE_MODS_LATCHED; + if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LOCKED) + led->which_mods |= XKB_STATE_MODS_LOCKED; + if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_EFFECTIVE) + led->which_mods |= XKB_STATE_MODS_EFFECTIVE; + if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_COMPAT) + led->which_mods |= XKB_STATE_MODS_EFFECTIVE; + + led->mods.mods = translate_mods(wire->realMods, wire->vmods, 0); + led->mods.mask = translate_mods(wire->mods, 0, 0); + + led->ctrls = translate_controls_mask(wire->ctrls); + + xcb_xkb_indicator_map_next(&iter); + } + } + + return true; +} + +static bool +get_indicator_map(struct xkb_keymap *keymap, xcb_connection_t *conn, + uint16_t device_id) +{ + xcb_xkb_get_indicator_map_cookie_t cookie = + xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK); + xcb_xkb_get_indicator_map_reply_t *reply = + xcb_xkb_get_indicator_map_reply(conn, cookie, NULL); + + FAIL_IF_BAD_REPLY(reply, "XkbGetIndicatorMap"); + + if (!get_indicators(keymap, conn, reply)) + goto fail; + + free(reply); + return true; + +fail: + free(reply); + return false; +} + +static bool +get_sym_interprets(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_compat_map_reply_t *reply) +{ + int length = xcb_xkb_get_compat_map_si_rtrn_length(reply); + xcb_xkb_sym_interpret_iterator_t iter = + xcb_xkb_get_compat_map_si_rtrn_iterator(reply); + + FAIL_UNLESS(reply->firstSIRtrn == 0); + FAIL_UNLESS(reply->nSIRtrn == reply->nTotalSI); + + keymap->num_sym_interprets = reply->nSIRtrn; + ALLOC_OR_FAIL(keymap->sym_interprets, keymap->num_sym_interprets); + + for (int i = 0; i < length; i++) { + xcb_xkb_sym_interpret_t *wire = iter.data; + struct xkb_sym_interpret *sym_interpret = &keymap->sym_interprets[i]; + + sym_interpret->sym = wire->sym; + + switch (wire->match & XCB_XKB_SYM_INTERP_MATCH_OP_MASK) { + case XCB_XKB_SYM_INTERPRET_MATCH_NONE_OF: + sym_interpret->match = MATCH_NONE; + break; + case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF_OR_NONE: + sym_interpret->match = MATCH_ANY_OR_NONE; + break; + case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF: + sym_interpret->match = MATCH_ANY; + break; + case XCB_XKB_SYM_INTERPRET_MATCH_ALL_OF: + sym_interpret->match = MATCH_ALL; + break; + case XCB_XKB_SYM_INTERPRET_MATCH_EXACTLY: + sym_interpret->match = MATCH_EXACTLY; + break; + } + + sym_interpret->level_one_only = + !!(wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY); + sym_interpret->mods = wire->mods; + + if (wire->virtualMod == NO_MODIFIER) + sym_interpret->virtual_mod = XKB_MOD_INVALID; + else + sym_interpret->virtual_mod = NUM_REAL_MODS + wire->virtualMod; + + sym_interpret->repeat = !!(wire->flags & 0x01); + translate_action(&sym_interpret->action, + (xcb_xkb_action_t *) &wire->action); + + xcb_xkb_sym_interpret_next(&iter); + } + + return true; + +fail: + return false; +} + +static bool +get_compat_map(struct xkb_keymap *keymap, xcb_connection_t *conn, + uint16_t device_id) +{ + xcb_xkb_get_compat_map_cookie_t cookie = + xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0); + xcb_xkb_get_compat_map_reply_t *reply = + xcb_xkb_get_compat_map_reply(conn, cookie, NULL); + + FAIL_IF_BAD_REPLY(reply, "XkbGetCompatMap"); + + if (!get_sym_interprets(keymap, conn, reply)) + goto fail; + + free(reply); + return true; + +fail: + free(reply); + return false; +} + +static bool +get_type_names(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_names_reply_t *reply, + xcb_xkb_get_names_value_list_t *list) +{ + int key_type_names_length = + xcb_xkb_get_names_value_list_type_names_length(reply, list); + xcb_atom_t *key_type_names_iter = + xcb_xkb_get_names_value_list_type_names(list); + int n_levels_per_type_length = + xcb_xkb_get_names_value_list_n_levels_per_type_length(reply, list); + uint8_t *n_levels_per_type_iter = + xcb_xkb_get_names_value_list_n_levels_per_type(list); + xcb_atom_t *kt_level_names_iter = + xcb_xkb_get_names_value_list_kt_level_names(list); + + FAIL_UNLESS(reply->nTypes == keymap->num_types); + FAIL_UNLESS(key_type_names_length == n_levels_per_type_length); + + for (int i = 0; i < key_type_names_length; i++) { + xcb_atom_t wire_type_name = *key_type_names_iter; + uint8_t wire_num_levels = *n_levels_per_type_iter; + struct xkb_key_type *type = &keymap->types[i]; + + /* Levels must have names. */ + FAIL_UNLESS(type->num_levels == wire_num_levels); + + ALLOC_OR_FAIL(type->level_names, type->num_levels); + + if (!adopt_atom(keymap->ctx, conn, wire_type_name, &type->name)) + goto fail; + + if (!adopt_atoms(keymap->ctx, conn, + kt_level_names_iter, type->level_names, + wire_num_levels)) + goto fail; + + kt_level_names_iter += wire_num_levels; + key_type_names_iter++; + n_levels_per_type_iter++; + } + + return true; + +fail: + return false; +} + +static bool +get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_names_reply_t *reply, + xcb_xkb_get_names_value_list_t *list) +{ + xcb_atom_t *iter = xcb_xkb_get_names_value_list_indicator_names(list); + + FAIL_UNLESS(msb_pos(reply->indicators) <= darray_size(keymap->leds)); + + for (int i = 0; i < NUM_INDICATORS; i++) { + if (reply->indicators & (1 << i)) { + xcb_atom_t wire = *iter; + struct xkb_led *led = &darray_item(keymap->leds, i); + + if (!adopt_atom(keymap->ctx, conn, wire, &led->name)) + return false; + + iter++; + } + } + + return true; + +fail: + return false; +} + +static bool +get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_names_reply_t *reply, + xcb_xkb_get_names_value_list_t *list) +{ + xcb_atom_t *iter = xcb_xkb_get_names_value_list_virtual_mod_names(list); + + /* + * GetMap's reply->virtualMods is always 0xffff. This one really + * tells us which vmods exist (a vmod must have a name), so we fix + * up the size here. + */ + darray_resize0(keymap->mods, NUM_REAL_MODS + msb_pos(reply->virtualMods)); + + for (int i = 0; i < NUM_VMODS; i++) { + if (reply->virtualMods & (1 << i)) { + xcb_atom_t wire = *iter; + struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i); + + if (!adopt_atom(keymap->ctx, conn, wire, &mod->name)) + return false; + + iter++; + } + } + + return true; +} + +static bool +get_group_names(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_names_reply_t *reply, + xcb_xkb_get_names_value_list_t *list) +{ + int length = xcb_xkb_get_names_value_list_groups_length(reply, list); + xcb_atom_t *iter = xcb_xkb_get_names_value_list_groups(list); + + keymap->num_group_names = msb_pos(reply->groupNames); + ALLOC_OR_FAIL(keymap->group_names, keymap->num_group_names); + + if (!adopt_atoms(keymap->ctx, conn, + iter, keymap->group_names, length)) + goto fail; + + return true; + +fail: + return false; +} + +static bool +get_key_names(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_names_reply_t *reply, + xcb_xkb_get_names_value_list_t *list) +{ + int length = xcb_xkb_get_names_value_list_key_names_length(reply, list); + xcb_xkb_key_name_iterator_t iter = + xcb_xkb_get_names_value_list_key_names_iterator(reply, list); + + FAIL_UNLESS(reply->minKeyCode == keymap->min_key_code); + FAIL_UNLESS(reply->maxKeyCode == keymap->max_key_code); + FAIL_UNLESS(reply->firstKey == keymap->min_key_code); + FAIL_UNLESS(reply->firstKey + reply->nKeys - 1 == keymap->max_key_code); + + for (int i = 0; i < length; i++) { + xcb_xkb_key_name_t *wire = iter.data; + xkb_atom_t *key_name = &keymap->keys[reply->firstKey + i].name; + + if (wire->name[0] == '\0') { + *key_name = XKB_ATOM_NONE; + } + else { + *key_name = xkb_atom_intern(keymap->ctx, wire->name, + strnlen(wire->name, + XCB_XKB_CONST_KEY_NAME_LENGTH)); + if (!*key_name) + return false; + } + + xcb_xkb_key_name_next(&iter); + } + + return true; + +fail: + return false; +} + +static bool +get_aliases(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_names_reply_t *reply, + xcb_xkb_get_names_value_list_t *list) +{ + int length = xcb_xkb_get_names_value_list_key_aliases_length(reply, list); + xcb_xkb_key_alias_iterator_t iter = + xcb_xkb_get_names_value_list_key_aliases_iterator(reply, list); + + keymap->num_key_aliases = reply->nKeyAliases; + ALLOC_OR_FAIL(keymap->key_aliases, keymap->num_key_aliases); + + for (int i = 0; i < length; i++) { + xcb_xkb_key_alias_t *wire = iter.data; + struct xkb_key_alias *alias = &keymap->key_aliases[i]; + + alias->real = + xkb_atom_intern(keymap->ctx, wire->real, + strnlen(wire->real, XCB_XKB_CONST_KEY_NAME_LENGTH)); + alias->alias = + xkb_atom_intern(keymap->ctx, wire->alias, + strnlen(wire->alias, XCB_XKB_CONST_KEY_NAME_LENGTH)); + if (!alias->real || !alias->alias) + goto fail; + + xcb_xkb_key_alias_next(&iter); + } + + return true; + +fail: + return false; +} + +static bool +get_names(struct xkb_keymap *keymap, xcb_connection_t *conn, + uint16_t device_id) +{ + static const xcb_xkb_name_detail_t required_names = + (XCB_XKB_NAME_DETAIL_KEYCODES | + XCB_XKB_NAME_DETAIL_SYMBOLS | + XCB_XKB_NAME_DETAIL_TYPES | + XCB_XKB_NAME_DETAIL_COMPAT | + XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | + XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | + XCB_XKB_NAME_DETAIL_INDICATOR_NAMES | + XCB_XKB_NAME_DETAIL_KEY_NAMES | + XCB_XKB_NAME_DETAIL_KEY_ALIASES | + XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES | + XCB_XKB_NAME_DETAIL_GROUP_NAMES); + + xcb_xkb_get_names_cookie_t cookie = + xcb_xkb_get_names(conn, device_id, required_names); + xcb_xkb_get_names_reply_t *reply = + xcb_xkb_get_names_reply(conn, cookie, NULL); + xcb_xkb_get_names_value_list_t list; + + FAIL_IF_BAD_REPLY(reply, "XkbGetNames"); + + if ((reply->which & required_names) != required_names) + goto fail; + + xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply), + reply->nTypes, + reply->indicators, + reply->virtualMods, + reply->groupNames, + reply->nKeys, + reply->nKeyAliases, + reply->nRadioGroups, + reply->which, + &list); + + if (!get_atom_name(conn, list.keycodesName, &keymap->keycodes_section_name) || + !get_atom_name(conn, list.symbolsName, &keymap->symbols_section_name) || + !get_atom_name(conn, list.typesName, &keymap->types_section_name) || + !get_atom_name(conn, list.compatName, &keymap->compat_section_name) || + !get_type_names(keymap, conn, reply, &list) || + !get_indicator_names(keymap, conn, reply, &list) || + !get_vmod_names(keymap, conn, reply, &list) || + !get_group_names(keymap, conn, reply, &list) || + !get_key_names(keymap, conn, reply, &list) || + !get_aliases(keymap, conn, reply, &list)) + goto fail; + + XkbEscapeMapName(keymap->keycodes_section_name); + XkbEscapeMapName(keymap->symbols_section_name); + XkbEscapeMapName(keymap->types_section_name); + XkbEscapeMapName(keymap->compat_section_name); + + free(reply); + return true; + +fail: + free(reply); + return false; +} + +static bool +get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn, + uint16_t device_id) +{ + xcb_xkb_get_controls_cookie_t cookie = + xcb_xkb_get_controls(conn, device_id); + xcb_xkb_get_controls_reply_t *reply = + xcb_xkb_get_controls_reply(conn, cookie, NULL); + + FAIL_IF_BAD_REPLY(reply, "XkbGetControls"); + + keymap->enabled_ctrls = translate_controls_mask(reply->enabledControls); + keymap->num_groups = reply->numGroups; + + FAIL_UNLESS(keymap->max_key_code < XCB_XKB_CONST_PER_KEY_BIT_ARRAY_SIZE * 8); + + for (int i = keymap->min_key_code; i <= keymap->max_key_code; i++) + keymap->keys[i].repeats = !!(reply->perKeyRepeat[i / 8] & (1 << (i % 8))); + + free(reply); + return true; + +fail: + free(reply); + return false; +} + +XKB_EXPORT struct xkb_keymap * +xkb_x11_keymap_new_from_device(struct xkb_context *ctx, + xcb_connection_t *conn, + int32_t device_id, + enum xkb_keymap_compile_flags flags) +{ + struct xkb_keymap *keymap; + const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1; + + if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) { + log_err_func(ctx, "unrecognized flags: %#x\n", flags); + return NULL; + } + + if (device_id < 0 || device_id > 255) { + log_err_func(ctx, "illegal device ID: %d\n", device_id); + return NULL; + } + + keymap = xkb_keymap_new(ctx, format, flags); + if (!keymap) + return NULL; + + if (!get_map(keymap, conn, device_id) || + !get_indicator_map(keymap, conn, device_id) || + !get_compat_map(keymap, conn, device_id) || + !get_names(keymap, conn, device_id) || + !get_controls(keymap, conn, device_id)) { + xkb_keymap_unref(keymap); + return NULL; + } + + return keymap; +} diff --git a/src/3rdparty/xkbcommon/src/x11/x11-priv.h b/src/3rdparty/xkbcommon/src/x11/x11-priv.h new file mode 100644 index 0000000000..03f9ee6710 --- /dev/null +++ b/src/3rdparty/xkbcommon/src/x11/x11-priv.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _XKBCOMMON_X11_PRIV_H +#define _XKBCOMMON_X11_PRIV_H + +#include + +#include "xkbcommon/xkbcommon-x11.h" +#include "keymap.h" + +/* Get a strdup'd name of an X atom. */ +bool +get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out); + +/* + * Make a xkb_atom_t's from X atoms (prefer to send as many as possible + * at once, to avoid many roundtrips). + * + * TODO: We can make this more flexible, such that @to doesn't have to + * be sequential. Then we can convert most adopt_atom() calls to + * adopt_atoms(). + * Atom caching would also likely be useful for avoiding quite a + * few requests. + */ +bool +adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn, + const xcb_atom_t *from, xkb_atom_t *to, size_t count); + +bool +adopt_atom(struct xkb_context *ctx, xcb_connection_t *conn, xcb_atom_t atom, + xkb_atom_t *out); + +#endif diff --git a/src/3rdparty/xkbcommon/src/x11/x11-state.c b/src/3rdparty/xkbcommon/src/x11/x11-state.c new file mode 100644 index 0000000000..da7dcc23c2 --- /dev/null +++ b/src/3rdparty/xkbcommon/src/x11/x11-state.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "x11-priv.h" + +static bool +update_initial_state(struct xkb_state *state, xcb_connection_t *conn, + uint16_t device_id) +{ + xcb_xkb_get_state_cookie_t cookie = + xcb_xkb_get_state(conn, device_id); + xcb_xkb_get_state_reply_t *reply = + xcb_xkb_get_state_reply(conn, cookie, NULL); + + if (!reply) + return false; + + xkb_state_update_mask(state, + reply->baseMods, + reply->latchedMods, + reply->lockedMods, + reply->baseGroup, + reply->latchedGroup, + reply->lockedGroup); + + free(reply); + return true; +} + +XKB_EXPORT struct xkb_state * +xkb_x11_state_new_from_device(struct xkb_keymap *keymap, + xcb_connection_t *conn, int32_t device_id) +{ + struct xkb_state *state; + + if (device_id < 0 || device_id > 255) { + log_err_func(keymap->ctx, "illegal device ID: %d", device_id); + return NULL; + } + + state = xkb_state_new(keymap); + if (!state) + return NULL; + + if (!update_initial_state(state, conn, device_id)) { + xkb_state_unref(state); + return NULL; + } + + return state; +} diff --git a/src/3rdparty/xkbcommon/src/xkb-keymap.c b/src/3rdparty/xkbcommon/src/xkb-keymap.c index 3df183a64f..7d991d535d 100644 --- a/src/3rdparty/xkbcommon/src/xkb-keymap.c +++ b/src/3rdparty/xkbcommon/src/xkb-keymap.c @@ -53,26 +53,6 @@ #include "keymap.h" #include "text.h" -static struct xkb_keymap * -xkb_keymap_new(struct xkb_context *ctx, - enum xkb_keymap_format format, - enum xkb_keymap_compile_flags flags) -{ - struct xkb_keymap *keymap; - - keymap = calloc(1, sizeof(*keymap)); - if (!keymap) - return NULL; - - keymap->refcnt = 1; - keymap->ctx = xkb_context_ref(ctx); - - keymap->format = format; - keymap->flags = flags; - - return keymap; -} - XKB_EXPORT struct xkb_keymap * xkb_keymap_ref(struct xkb_keymap *keymap) { @@ -83,30 +63,34 @@ xkb_keymap_ref(struct xkb_keymap *keymap) XKB_EXPORT void xkb_keymap_unref(struct xkb_keymap *keymap) { - unsigned int i, j; - struct xkb_key *key; - if (!keymap || --keymap->refcnt > 0) return; if (keymap->keys) { + struct xkb_key *key; xkb_foreach_key(key, keymap) { - for (i = 0; i < key->num_groups; i++) { - for (j = 0; j < XkbKeyGroupWidth(key, i); j++) - if (key->groups[i].levels[j].num_syms > 1) - free(key->groups[i].levels[j].u.syms); - free(key->groups[i].levels); + if (key->groups) { + for (unsigned i = 0; i < key->num_groups; i++) { + if (key->groups[i].levels) { + for (unsigned j = 0; j < XkbKeyGroupWidth(key, i); j++) + if (key->groups[i].levels[j].num_syms > 1) + free(key->groups[i].levels[j].u.syms); + free(key->groups[i].levels); + } + } + free(key->groups); } - free(key->groups); } free(keymap->keys); } - for (i = 0; i < keymap->num_types; i++) { - free(keymap->types[i].entries); - free(keymap->types[i].level_names); + if (keymap->types) { + for (unsigned i = 0; i < keymap->num_types; i++) { + free(keymap->types[i].entries); + free(keymap->types[i].level_names); + } + free(keymap->types); } - free(keymap->types); - darray_free(keymap->sym_interprets); + free(keymap->sym_interprets); free(keymap->key_aliases); free(keymap->group_names); darray_free(keymap->mods); @@ -190,35 +174,8 @@ xkb_keymap_new_from_string(struct xkb_context *ctx, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { - struct xkb_keymap *keymap; - const struct xkb_keymap_format_ops *ops; - - ops = get_keymap_format_ops(format); - if (!ops || !ops->keymap_new_from_string) { - log_err_func(ctx, "unsupported keymap format: %d\n", format); - return NULL; - } - - if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) { - log_err_func(ctx, "unrecognized flags: %#x\n", flags); - return NULL; - } - - if (!string) { - log_err_func1(ctx, "no string specified\n"); - return NULL; - } - - keymap = xkb_keymap_new(ctx, format, flags); - if (!keymap) - return NULL; - - if (!ops->keymap_new_from_string(keymap, string)) { - xkb_keymap_unref(keymap); - return NULL; - } - - return keymap; + return xkb_keymap_new_from_buffer(ctx, string, strlen(string), + format, flags); } XKB_EXPORT struct xkb_keymap * @@ -250,7 +207,7 @@ xkb_keymap_new_from_buffer(struct xkb_context *ctx, if (!keymap) return NULL; - if (!ops->keymap_new_from_buffer(keymap, buffer, length)) { + if (!ops->keymap_new_from_string(keymap, buffer, length)) { xkb_keymap_unref(keymap); return NULL; } @@ -512,44 +469,38 @@ err: return 0; } -/** - * Simple boolean specifying whether or not the key should repeat. - */ -XKB_EXPORT int -xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc) +XKB_EXPORT xkb_keycode_t +xkb_keymap_min_keycode(struct xkb_keymap *keymap) { - const struct xkb_key *key = XkbKey(keymap, kc); - - if (!key) - return 0; + return keymap->min_key_code; +} - return key->repeats; +XKB_EXPORT xkb_keycode_t +xkb_keymap_max_keycode(struct xkb_keymap *keymap) +{ + return keymap->max_key_code; } -struct xkb_key * -XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases) +XKB_EXPORT void +xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter, + void *data) { struct xkb_key *key; xkb_foreach_key(key, keymap) - if (key->name == name) - return key; - - if (use_aliases) { - xkb_atom_t new_name = XkbResolveKeyAlias(keymap, name); - if (new_name != XKB_ATOM_NONE) - return XkbKeyByName(keymap, new_name, false); - } - - return NULL; + iter(keymap, key->keycode, data); } -xkb_atom_t -XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name) +/** + * Simple boolean specifying whether or not the key should repeat. + */ +XKB_EXPORT int +xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc) { - for (unsigned i = 0; i < keymap->num_key_aliases; i++) - if (keymap->key_aliases[i].alias == name) - return keymap->key_aliases[i].real; + const struct xkb_key *key = XkbKey(keymap, kc); - return XKB_ATOM_NONE; + if (!key) + return 0; + + return key->repeats; } diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/action.c b/src/3rdparty/xkbcommon/src/xkbcomp/action.c index 88323f9952..2bd0bd1589 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/action.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/action.c @@ -56,18 +56,22 @@ #include "expr.h" #include "action.h" -static const ExprDef constTrue = { - .common = { .type = STMT_EXPR, .next = NULL }, - .op = EXPR_VALUE, - .value_type = EXPR_TYPE_BOOLEAN, - .value = { .ival = 1 }, +static const ExprBoolean constTrue = { + .expr = { + .common = { .type = STMT_EXPR, .next = NULL }, + .op = EXPR_VALUE, + .value_type = EXPR_TYPE_BOOLEAN, + }, + .set = true, }; -static const ExprDef constFalse = { - .common = { .type = STMT_EXPR, .next = NULL }, - .op = EXPR_VALUE, - .value_type = EXPR_TYPE_BOOLEAN, - .value = { .ival = 0 }, +static const ExprBoolean constFalse = { + .expr = { + .common = { .type = STMT_EXPR, .next = NULL }, + .op = EXPR_VALUE, + .value_type = EXPR_TYPE_BOOLEAN, + }, + .set = false, }; enum action_field { @@ -214,17 +218,6 @@ ReportActionNotArray(struct xkb_keymap *keymap, enum xkb_action_type action, return false; } -static inline bool -ReportNotFound(struct xkb_keymap *keymap, enum xkb_action_type action, - enum action_field field, const char *what, const char *bad) -{ - log_err(keymap->ctx, - "%s named %s not found; " - "Ignoring the %s field of an %s action\n", - what, bad, fieldText(field), ActionTypeText(action)); - return false; -} - static bool HandleNoAction(struct xkb_keymap *keymap, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, @@ -265,9 +258,9 @@ CheckModifierField(struct xkb_keymap *keymap, enum xkb_action_type action, const ExprDef *value, enum xkb_action_flags *flags_inout, xkb_mod_mask_t *mods_rtrn) { - if (value->op == EXPR_IDENT) { + if (value->expr.op == EXPR_IDENT) { const char *valStr; - valStr = xkb_atom_text(keymap->ctx, value->value.str); + valStr = xkb_atom_text(keymap->ctx, value->ident.ident); if (valStr && (istreq(valStr, "usemodmapmods") || istreq(valStr, "modmapmods"))) { @@ -367,9 +360,9 @@ CheckGroupField(struct xkb_keymap *keymap, unsigned action, { const ExprDef *spec; - if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) { + if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) { *flags_inout &= ~ACTION_ABSOLUTE_SWITCH; - spec = value->value.child; + spec = value->unary.child; } else { *flags_inout |= ACTION_ABSOLUTE_SWITCH; @@ -380,9 +373,9 @@ CheckGroupField(struct xkb_keymap *keymap, unsigned action, return ReportMismatch(keymap, action, ACTION_FIELD_GROUP, "integer (range 1..8)"); - if (value->op == EXPR_NEGATE) + if (value->expr.op == EXPR_NEGATE) *grp_rtrn = -*grp_rtrn; - else if (value->op != EXPR_UNARY_PLUS) + else if (value->expr.op != EXPR_UNARY_PLUS) (*grp_rtrn)--; return true; @@ -464,18 +457,14 @@ HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action, const ExprDef *value) { struct xkb_pointer_action *act = &action->ptr; - bool absolute; if (array_ndx && (field == ACTION_FIELD_X || field == ACTION_FIELD_Y)) return ReportActionNotArray(keymap, action->type, field); if (field == ACTION_FIELD_X || field == ACTION_FIELD_Y) { int val; - - if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) - absolute = false; - else - absolute = true; + const bool absolute = (value->expr.op != EXPR_NEGATE && + value->expr.op != EXPR_UNARY_PLUS); if (!ExprResolveInteger(keymap->ctx, value, &val)) return ReportMismatch(keymap, action->type, field, "integer"); @@ -613,9 +602,10 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action, if (array_ndx) return ReportActionNotArray(keymap, action->type, field); - if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) { + if (value->expr.op == EXPR_NEGATE || + value->expr.op == EXPR_UNARY_PLUS) { act->flags &= ~ACTION_ABSOLUTE_SWITCH; - button = value->value.child; + button = value->unary.child; } else { act->flags |= ACTION_ABSOLUTE_SWITCH; @@ -639,7 +629,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action, return false; } - act->value = (value->op == EXPR_NEGATE ? -btn: btn); + act->value = (value->expr.op == EXPR_NEGATE ? -btn: btn); return true; } @@ -660,9 +650,10 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action, if (array_ndx) return ReportActionNotArray(keymap, action->type, field); - if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) { + if (value->expr.op == EXPR_NEGATE || + value->expr.op == EXPR_UNARY_PLUS) { act->flags &= ~ACTION_ABSOLUTE_SWITCH; - scrn = value->value.child; + scrn = value->unary.child; } else { act->flags |= ACTION_ABSOLUTE_SWITCH; @@ -680,7 +671,7 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action, return false; } - act->screen = (value->op == EXPR_NEGATE ? -val : val); + act->screen = (value->expr.op == EXPR_NEGATE ? -val : val); return true; } else if (field == ACTION_FIELD_SAME) { @@ -861,13 +852,13 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap, const char *str; unsigned handler_type; - if (def->op != EXPR_ACTION_DECL) { + if (def->expr.op != EXPR_ACTION_DECL) { log_err(keymap->ctx, "Expected an action definition, found %s\n", - expr_op_type_to_string(def->op)); + expr_op_type_to_string(def->expr.op)); return false; } - str = xkb_atom_text(keymap->ctx, def->value.action.name); + str = xkb_atom_text(keymap->ctx, def->action.name); if (!stringToAction(str, &handler_type)) { log_err(keymap->ctx, "Unknown action %s\n", str); return false; @@ -885,24 +876,24 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap, * particular instance, e.g. "modifiers" and "clearLocks" in: * SetMods(modifiers=Alt,clearLocks); */ - for (arg = def->value.action.args; arg != NULL; + for (arg = def->action.args; arg != NULL; arg = (ExprDef *) arg->common.next) { const ExprDef *value; ExprDef *field, *arrayRtrn; const char *elemRtrn, *fieldRtrn; enum action_field fieldNdx; - if (arg->op == EXPR_ASSIGN) { - field = arg->value.binary.left; - value = arg->value.binary.right; + if (arg->expr.op == EXPR_ASSIGN) { + field = arg->binary.left; + value = arg->binary.right; } - else if (arg->op == EXPR_NOT || arg->op == EXPR_INVERT) { - field = arg->value.child; - value = &constFalse; + else if (arg->expr.op == EXPR_NOT || arg->expr.op == EXPR_INVERT) { + field = arg->unary.child; + value = (const ExprDef *) &constFalse; } else { field = arg; - value = &constTrue; + value = (const ExprDef *) &constTrue; } if (!ExprResolveLhs(keymap->ctx, field, &elemRtrn, &fieldRtrn, diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c index c9b7cb0a3e..d470884e78 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c @@ -70,57 +70,173 @@ AppendStmt(ParseCommon *to, ParseCommon *append) return to; } -ExprDef * -ExprCreate(enum expr_op_type op, enum expr_value_type type) +static ExprDef * +ExprCreate(enum expr_op_type op, enum expr_value_type type, size_t size) { - ExprDef *expr = malloc(sizeof(*expr)); + ExprDef *expr = malloc(size); if (!expr) return NULL; expr->common.type = STMT_EXPR; expr->common.next = NULL; - expr->op = op; - expr->value_type = type; + expr->expr.op = op; + expr->expr.value_type = type; return expr; } +#define EXPR_CREATE(type_, name_, op_, value_type_) \ + ExprDef *name_ = ExprCreate(op_, value_type_, sizeof(type_)); \ + if (!name_) \ + return NULL; + +ExprDef * +ExprCreateString(xkb_atom_t str) +{ + EXPR_CREATE(ExprString, expr, EXPR_VALUE, EXPR_TYPE_STRING); + expr->string.str = str; + return expr; +} + +ExprDef * +ExprCreateInteger(int ival) +{ + EXPR_CREATE(ExprInteger, expr, EXPR_VALUE, EXPR_TYPE_INT); + expr->integer.ival = ival; + return expr; +} + +ExprDef * +ExprCreateBoolean(bool set) +{ + EXPR_CREATE(ExprBoolean, expr, EXPR_VALUE, EXPR_TYPE_BOOLEAN); + expr->boolean.set = set; + return expr; +} + +ExprDef * +ExprCreateKeyName(xkb_atom_t key_name) +{ + EXPR_CREATE(ExprKeyName, expr, EXPR_VALUE, EXPR_TYPE_KEYNAME); + expr->key_name.key_name = key_name; + return expr; +} + +ExprDef * +ExprCreateIdent(xkb_atom_t ident) +{ + EXPR_CREATE(ExprIdent, expr, EXPR_IDENT, EXPR_TYPE_UNKNOWN); + expr->ident.ident = ident; + return expr; +} + ExprDef * ExprCreateUnary(enum expr_op_type op, enum expr_value_type type, ExprDef *child) { - ExprDef *expr = malloc(sizeof(*expr)); - if (!expr) - return NULL; + EXPR_CREATE(ExprUnary, expr, op, type); + expr->unary.child = child; + return expr; +} - expr->common.type = STMT_EXPR; - expr->common.next = NULL; - expr->op = op; - expr->value_type = type; - expr->value.child = child; +ExprDef * +ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right) +{ + EXPR_CREATE(ExprBinary, expr, op, EXPR_TYPE_UNKNOWN); + + if (op == EXPR_ASSIGN || left->expr.value_type == EXPR_TYPE_UNKNOWN) + expr->expr.value_type = right->expr.value_type; + else if (left->expr.value_type == right->expr.value_type || + right->expr.value_type == EXPR_TYPE_UNKNOWN) + expr->expr.value_type = left->expr.value_type; + expr->binary.left = left; + expr->binary.right = right; return expr; } ExprDef * -ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right) +ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field) { - ExprDef *expr = malloc(sizeof(*expr)); - if (!expr) - return NULL; + EXPR_CREATE(ExprFieldRef, expr, EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN); + expr->field_ref.element = element; + expr->field_ref.field = field; + return expr; +} - expr->common.type = STMT_EXPR; - expr->common.next = NULL; - expr->op = op; - if (op == EXPR_ASSIGN || left->value_type == EXPR_TYPE_UNKNOWN) - expr->value_type = right->value_type; - else if (left->value_type == right->value_type || - right->value_type == EXPR_TYPE_UNKNOWN) - expr->value_type = left->value_type; - else - expr->value_type = EXPR_TYPE_UNKNOWN; - expr->value.binary.left = left; - expr->value.binary.right = right; +ExprDef * +ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry) +{ + EXPR_CREATE(ExprArrayRef, expr, EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN); + expr->array_ref.element = element; + expr->array_ref.field = field; + expr->array_ref.entry = entry; + return expr; +} + +ExprDef * +ExprCreateAction(xkb_atom_t name, ExprDef *args) +{ + EXPR_CREATE(ExprAction, expr, EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN); + expr->action.name = name; + expr->action.args = args; + return expr; +} + +ExprDef * +ExprCreateKeysymList(xkb_keysym_t sym) +{ + EXPR_CREATE(ExprKeysymList, expr, EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS); + + darray_init(expr->keysym_list.syms); + darray_init(expr->keysym_list.symsMapIndex); + darray_init(expr->keysym_list.symsNumEntries); + + darray_append(expr->keysym_list.syms, sym); + darray_append(expr->keysym_list.symsMapIndex, 0); + darray_append(expr->keysym_list.symsNumEntries, 1); + + return expr; +} + +ExprDef * +ExprCreateMultiKeysymList(ExprDef *expr) +{ + size_t nLevels = darray_size(expr->keysym_list.symsMapIndex); + + darray_resize(expr->keysym_list.symsMapIndex, 1); + darray_resize(expr->keysym_list.symsNumEntries, 1); + darray_item(expr->keysym_list.symsMapIndex, 0) = 0; + darray_item(expr->keysym_list.symsNumEntries, 0) = nLevels; + + return expr; +} + +ExprDef * +ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym) +{ + size_t nSyms = darray_size(expr->keysym_list.syms); + + darray_append(expr->keysym_list.symsMapIndex, nSyms); + darray_append(expr->keysym_list.symsNumEntries, 1); + darray_append(expr->keysym_list.syms, sym); + + return expr; +} + +ExprDef * +ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append) +{ + size_t nSyms = darray_size(expr->keysym_list.syms); + size_t numEntries = darray_size(append->keysym_list.syms); + + darray_append(expr->keysym_list.symsMapIndex, nSyms); + darray_append(expr->keysym_list.symsNumEntries, numEntries); + darray_append_items(expr->keysym_list.syms, + darray_mem(append->keysym_list.syms, 0), numEntries); + + darray_resize(append->keysym_list.syms, 0); + FreeStmt(&append->common); return expr; } @@ -186,22 +302,14 @@ VarCreate(ExprDef *name, ExprDef *value) } VarDef * -BoolVarCreate(xkb_atom_t nameToken, unsigned set) +BoolVarCreate(xkb_atom_t ident, bool set) { - ExprDef *name, *value; - VarDef *def; - - name = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN); - name->value.str = nameToken; - value = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN); - value->value.uval = set; - def = VarCreate(name, value); - - return def; + return VarCreate((ExprDef *) ExprCreateIdent(ident), + (ExprDef *) ExprCreateBoolean(set)); } InterpDef * -InterpCreate(char *sym, ExprDef *match) +InterpCreate(xkb_keysym_t sym, ExprDef *match) { InterpDef *def = malloc(sizeof(*def)); if (!def) @@ -232,7 +340,7 @@ KeyTypeCreate(xkb_atom_t name, VarDef *body) } SymbolsDef * -SymbolsCreate(xkb_atom_t keyName, ExprDef *symbols) +SymbolsCreate(xkb_atom_t keyName, VarDef *symbols) { SymbolsDef *def = malloc(sizeof(*def)); if (!def) @@ -312,83 +420,6 @@ LedNameCreate(int ndx, ExprDef *name, bool virtual) return def; } -ExprDef * -ActionCreate(xkb_atom_t name, ExprDef *args) -{ - ExprDef *act = malloc(sizeof(*act)); - if (!act) - return NULL; - - act->common.type = STMT_EXPR; - act->common.next = NULL; - act->op = EXPR_ACTION_DECL; - act->value.action.name = name; - act->value.action.args = args; - - return act; -} - -ExprDef * -CreateKeysymList(char *sym) -{ - ExprDef *def; - - def = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS); - - darray_init(def->value.list.syms); - darray_init(def->value.list.symsMapIndex); - darray_init(def->value.list.symsNumEntries); - - darray_append(def->value.list.syms, sym); - darray_append(def->value.list.symsMapIndex, 0); - darray_append(def->value.list.symsNumEntries, 1); - - return def; -} - -ExprDef * -CreateMultiKeysymList(ExprDef *list) -{ - size_t nLevels = darray_size(list->value.list.symsMapIndex); - - darray_resize(list->value.list.symsMapIndex, 1); - darray_resize(list->value.list.symsNumEntries, 1); - darray_item(list->value.list.symsMapIndex, 0) = 0; - darray_item(list->value.list.symsNumEntries, 0) = nLevels; - - return list; -} - -ExprDef * -AppendKeysymList(ExprDef *list, char *sym) -{ - size_t nSyms = darray_size(list->value.list.syms); - - darray_append(list->value.list.symsMapIndex, nSyms); - darray_append(list->value.list.symsNumEntries, 1); - darray_append(list->value.list.syms, sym); - - return list; -} - -ExprDef * -AppendMultiKeysymList(ExprDef *list, ExprDef *append) -{ - size_t nSyms = darray_size(list->value.list.syms); - size_t numEntries = darray_size(append->value.list.syms); - - darray_append(list->value.list.symsMapIndex, nSyms); - darray_append(list->value.list.symsNumEntries, numEntries); - darray_append_items(list->value.list.syms, - darray_mem(append->value.list.syms, 0), - numEntries); - - darray_resize(append->value.list.syms, 0); - FreeStmt(&append->common); - - return list; -} - static void FreeInclude(IncludeStmt *incl); @@ -464,30 +495,6 @@ err: return NULL; } -static void -EscapeMapName(char *name) -{ - /* - * All latin-1 alphanumerics, plus parens, slash, minus, underscore and - * wildcards. - */ - static const unsigned char legal[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, - 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff - }; - - if (!name) - return; - - while (*name) { - if (!(legal[*name / 8] & (1 << (*name % 8)))) - *name = '_'; - name++; - } -} - XkbFile * XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name, ParseCommon *defs, enum xkb_map_flags flags) @@ -498,7 +505,7 @@ XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name, if (!file) return NULL; - EscapeMapName(name); + XkbEscapeMapName(name); file->file_type = type; file->topName = strdup_safe(name); file->name = name; @@ -549,18 +556,16 @@ err: static void FreeExpr(ExprDef *expr) { - char **sym; - if (!expr) return; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_ACTION_LIST: case EXPR_NEGATE: case EXPR_UNARY_PLUS: case EXPR_NOT: case EXPR_INVERT: - FreeStmt(&expr->value.child->common); + FreeStmt(&expr->unary.child->common); break; case EXPR_DIVIDE: @@ -568,24 +573,22 @@ FreeExpr(ExprDef *expr) case EXPR_SUBTRACT: case EXPR_MULTIPLY: case EXPR_ASSIGN: - FreeStmt(&expr->value.binary.left->common); - FreeStmt(&expr->value.binary.right->common); + FreeStmt(&expr->binary.left->common); + FreeStmt(&expr->binary.right->common); break; case EXPR_ACTION_DECL: - FreeStmt(&expr->value.action.args->common); + FreeStmt(&expr->action.args->common); break; case EXPR_ARRAY_REF: - FreeStmt(&expr->value.array.entry->common); + FreeStmt(&expr->array_ref.entry->common); break; case EXPR_KEYSYM_LIST: - darray_foreach(sym, expr->value.list.syms) - free(*sym); - darray_free(expr->value.list.syms); - darray_free(expr->value.list.symsMapIndex); - darray_free(expr->value.list.symsNumEntries); + darray_free(expr->keysym_list.syms); + darray_free(expr->keysym_list.symsMapIndex); + darray_free(expr->keysym_list.symsNumEntries); break; default: @@ -640,7 +643,6 @@ FreeStmt(ParseCommon *stmt) FreeStmt(&u.keyType->body->common); break; case STMT_INTERP: - free(u.interp->sym); FreeStmt(&u.interp->match->common); FreeStmt(&u.interp->def->common); break; diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h index 0ecd124145..8146b066d1 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h +++ b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h @@ -31,7 +31,19 @@ ParseCommon * AppendStmt(ParseCommon *to, ParseCommon *append); ExprDef * -ExprCreate(enum expr_op_type op, enum expr_value_type type); +ExprCreateString(xkb_atom_t str); + +ExprDef * +ExprCreateInteger(int ival); + +ExprDef * +ExprCreateBoolean(bool set); + +ExprDef * +ExprCreateKeyName(xkb_atom_t key_name); + +ExprDef * +ExprCreateIdent(xkb_atom_t ident); ExprDef * ExprCreateUnary(enum expr_op_type op, enum expr_value_type type, @@ -40,6 +52,27 @@ ExprCreateUnary(enum expr_op_type op, enum expr_value_type type, ExprDef * ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right); +ExprDef * +ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field); + +ExprDef * +ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry); + +ExprDef * +ExprCreateAction(xkb_atom_t name, ExprDef *args); + +ExprDef * +ExprCreateMultiKeysymList(ExprDef *list); + +ExprDef * +ExprCreateKeysymList(xkb_keysym_t sym); + +ExprDef * +ExprAppendMultiKeysymList(ExprDef *list, ExprDef *append); + +ExprDef * +ExprAppendKeysymList(ExprDef *list, xkb_keysym_t sym); + KeycodeDef * KeycodeCreate(xkb_atom_t name, int64_t value); @@ -53,16 +86,16 @@ VarDef * VarCreate(ExprDef *name, ExprDef *value); VarDef * -BoolVarCreate(xkb_atom_t nameToken, unsigned set); +BoolVarCreate(xkb_atom_t ident, bool set); InterpDef * -InterpCreate(char *sym, ExprDef *match); +InterpCreate(xkb_keysym_t sym, ExprDef *match); KeyTypeDef * KeyTypeCreate(xkb_atom_t name, VarDef *body); SymbolsDef * -SymbolsCreate(xkb_atom_t keyName, ExprDef *symbols); +SymbolsCreate(xkb_atom_t keyName, VarDef *symbols); GroupCompatDef * GroupCompatCreate(int group, ExprDef *def); @@ -76,27 +109,12 @@ LedMapCreate(xkb_atom_t name, VarDef *body); LedNameDef * LedNameCreate(int ndx, ExprDef *name, bool virtual); -ExprDef * -ActionCreate(xkb_atom_t name, ExprDef *args); - -ExprDef * -CreateMultiKeysymList(ExprDef *list); - -ExprDef * -CreateKeysymList(char *sym); - -ExprDef * -AppendMultiKeysymList(ExprDef *list, ExprDef *append); - -ExprDef * -AppendKeysymList(ExprDef *list, char *sym); - IncludeStmt * IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge); XkbFile * XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name, - ParseCommon *defs, unsigned flags); + ParseCommon *defs, enum xkb_map_flags flags); void FreeStmt(ParseCommon *stmt); diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/ast.h b/src/3rdparty/xkbcommon/src/xkbcomp/ast.h index c430a772ae..489b33193c 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/ast.h +++ b/src/3rdparty/xkbcommon/src/xkbcomp/ast.h @@ -143,9 +143,11 @@ expr_op_type_to_string(enum expr_op_type type); const char * expr_value_type_to_string(enum expr_value_type type); -typedef struct _ParseCommon { - enum stmt_type type; +/* This struct contains fields common to all other AST nodes. It is only + * ever embedded in other structs, so save some memory by packing it. */ +typedef struct ATTR_PACKED _ParseCommon { struct _ParseCommon *next; + enum stmt_type type; } ParseCommon; typedef struct _IncludeStmt { @@ -158,40 +160,92 @@ typedef struct _IncludeStmt { struct _IncludeStmt *next_incl; } IncludeStmt; -typedef struct _Expr { +typedef struct { ParseCommon common; enum expr_op_type op; enum expr_value_type value_type; - union { - struct { - struct _Expr *left; - struct _Expr *right; - } binary; - struct { - xkb_atom_t element; - xkb_atom_t field; - } field; - struct { - xkb_atom_t element; - xkb_atom_t field; - struct _Expr *entry; - } array; - struct { - xkb_atom_t name; - struct _Expr *args; - } action; - struct { - darray(char *) syms; - darray(int) symsMapIndex; - darray(unsigned int) symsNumEntries; - } list; - struct _Expr *child; - xkb_atom_t str; - unsigned uval; - int ival; - xkb_atom_t keyName; - } value; -} ExprDef; +} ExprCommon; + +typedef union ExprDef ExprDef; + +typedef struct { + ExprCommon expr; + xkb_atom_t ident; +} ExprIdent; + +typedef struct { + ExprCommon expr; + xkb_atom_t str; +} ExprString; + +typedef struct { + ExprCommon expr; + bool set; +} ExprBoolean; + +typedef struct { + ExprCommon expr; + int ival; +} ExprInteger; + +typedef struct { + ExprCommon expr; + xkb_atom_t key_name; +} ExprKeyName; + +typedef struct { + ExprCommon expr; + ExprDef *left; + ExprDef *right; +} ExprBinary; + +typedef struct { + ExprCommon expr; + ExprDef *child; +} ExprUnary; + +typedef struct { + ExprCommon expr; + xkb_atom_t element; + xkb_atom_t field; +} ExprFieldRef; + +typedef struct { + ExprCommon expr; + xkb_atom_t element; + xkb_atom_t field; + ExprDef *entry; +} ExprArrayRef; + +typedef struct { + ExprCommon expr; + xkb_atom_t name; + ExprDef *args; +} ExprAction; + +typedef struct { + ExprCommon expr; + darray(xkb_keysym_t) syms; + darray(int) symsMapIndex; + darray(unsigned int) symsNumEntries; +} ExprKeysymList; + +union ExprDef { + ParseCommon common; + /* Maybe someday we can use C11 anonymous struct for ExprCommon here. */ + ExprCommon expr; + ExprIdent ident; + ExprString string; + ExprBoolean boolean; + ExprInteger integer; + ExprKeyName key_name; + ExprBinary binary; + ExprUnary unary; + ExprFieldRef field_ref; + ExprArrayRef array_ref; + ExprAction action; + ExprKeysymList keysym_list; +}; typedef struct { ParseCommon common; @@ -232,7 +286,7 @@ typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t keyName; - ExprDef *symbols; + VarDef *symbols; } SymbolsDef; typedef struct { @@ -252,7 +306,7 @@ typedef struct { typedef struct { ParseCommon common; enum merge_mode merge; - char *sym; + xkb_keysym_t sym; ExprDef *match; VarDef *def; } InterpDef; diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/compat.c b/src/3rdparty/xkbcommon/src/xkbcomp/compat.c index 5682895430..fffb2d34b2 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/compat.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/compat.c @@ -432,19 +432,19 @@ ResolveStateAndPredicate(ExprDef *expr, enum xkb_match_operation *pred_rtrn, } *pred_rtrn = MATCH_EXACTLY; - if (expr->op == EXPR_ACTION_DECL) { + if (expr->expr.op == EXPR_ACTION_DECL) { const char *pred_txt = xkb_atom_text(info->keymap->ctx, - expr->value.action.name); + expr->action.name); if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn)) { log_err(info->keymap->ctx, "Illegal modifier predicate \"%s\"; Ignored\n", pred_txt); return false; } - expr = expr->value.action.args; + expr = expr->action.args; } - else if (expr->op == EXPR_IDENT) { + else if (expr->expr.op == EXPR_IDENT) { const char *pred_txt = xkb_atom_text(info->keymap->ctx, - expr->value.str); + expr->ident.ident); if (pred_txt && istreq(pred_txt, "any")) { *pred_rtrn = MATCH_ANY; *mods_rtrn = MOD_REAL_MASK_ALL; @@ -805,7 +805,7 @@ HandleInterpBody(CompatInfo *info, VarDef *def, SymInterpInfo *si) ExprDef *arrayNdx; for (; def; def = (VarDef *) def->common.next) { - if (def->name && def->name->op == EXPR_FIELD_REF) { + if (def->name && def->name->expr.op == EXPR_FIELD_REF) { log_err(info->keymap->ctx, "Cannot set a global default value from within an interpret statement; " "Move statements to the global file scope\n"); @@ -840,15 +840,7 @@ HandleInterpDef(CompatInfo *info, InterpDef *def, enum merge_mode merge) si = info->default_interp; si.merge = merge = (def->merge == MERGE_DEFAULT ? merge : def->merge); - - if (!LookupKeysym(def->sym, &si.interp.sym)) { - log_err(info->keymap->ctx, - "Could not resolve keysym %s; " - "Symbol interpretation ignored\n", - def->sym); - return false; - } - + si.interp.sym = def->sym; si.interp.match = pred; si.interp.mods = mods; @@ -941,7 +933,7 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge) break; default: log_err(info->keymap->ctx, - "Interpretation files may not include other types; " + "Compat files may not include other types; " "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; @@ -958,15 +950,21 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge) } } +/* Temporary struct for CopyInterps. */ +struct collect { + darray(struct xkb_sym_interpret) sym_interprets; +}; + static void -CopyInterps(CompatInfo *info, bool needSymbol, enum xkb_match_operation pred) +CopyInterps(CompatInfo *info, bool needSymbol, enum xkb_match_operation pred, + struct collect *collect) { SymInterpInfo *si; darray_foreach(si, info->interps) if (si->interp.match == pred && (si->interp.sym != XKB_KEY_NoSymbol) == needSymbol) - darray_append(info->keymap->sym_interprets, si->interp); + darray_append(collect->sym_interprets, si->interp); } static void @@ -1025,19 +1023,26 @@ static bool CopyCompatToKeymap(struct xkb_keymap *keymap, CompatInfo *info) { keymap->compat_section_name = strdup_safe(info->name); + XkbEscapeMapName(keymap->compat_section_name); if (!darray_empty(info->interps)) { + struct collect collect; + darray_init(collect.sym_interprets); + /* Most specific to least specific. */ - CopyInterps(info, true, MATCH_EXACTLY); - CopyInterps(info, true, MATCH_ALL); - CopyInterps(info, true, MATCH_NONE); - CopyInterps(info, true, MATCH_ANY); - CopyInterps(info, true, MATCH_ANY_OR_NONE); - CopyInterps(info, false, MATCH_EXACTLY); - CopyInterps(info, false, MATCH_ALL); - CopyInterps(info, false, MATCH_NONE); - CopyInterps(info, false, MATCH_ANY); - CopyInterps(info, false, MATCH_ANY_OR_NONE); + CopyInterps(info, true, MATCH_EXACTLY, &collect); + CopyInterps(info, true, MATCH_ALL, &collect); + CopyInterps(info, true, MATCH_NONE, &collect); + CopyInterps(info, true, MATCH_ANY, &collect); + CopyInterps(info, true, MATCH_ANY_OR_NONE, &collect); + CopyInterps(info, false, MATCH_EXACTLY, &collect); + CopyInterps(info, false, MATCH_ALL, &collect); + CopyInterps(info, false, MATCH_NONE, &collect); + CopyInterps(info, false, MATCH_ANY, &collect); + CopyInterps(info, false, MATCH_ANY_OR_NONE, &collect); + + keymap->num_sym_interprets = darray_size(collect.sym_interprets); + keymap->sym_interprets = darray_mem(collect.sym_interprets, 0); } CopyLedMapDefs(info); diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/expr.c b/src/3rdparty/xkbcommon/src/xkbcomp/expr.c index dc64d7891f..ba71208f7e 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/expr.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/expr.c @@ -37,26 +37,26 @@ ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, const char **elem_rtrn, const char **field_rtrn, ExprDef **index_rtrn) { - switch (expr->op) { + switch (expr->expr.op) { case EXPR_IDENT: *elem_rtrn = NULL; - *field_rtrn = xkb_atom_text(ctx, expr->value.str); + *field_rtrn = xkb_atom_text(ctx, expr->ident.ident); *index_rtrn = NULL; return true; case EXPR_FIELD_REF: - *elem_rtrn = xkb_atom_text(ctx, expr->value.field.element); - *field_rtrn = xkb_atom_text(ctx, expr->value.field.field); + *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element); + *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field); *index_rtrn = NULL; return true; case EXPR_ARRAY_REF: - *elem_rtrn = xkb_atom_text(ctx, expr->value.array.element); - *field_rtrn = xkb_atom_text(ctx, expr->value.array.field); - *index_rtrn = expr->value.array.entry; + *elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element); + *field_rtrn = xkb_atom_text(ctx, expr->array_ref.field); + *index_rtrn = expr->array_ref.entry; return true; default: break; } - log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->op); + log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op); return false; } @@ -127,19 +127,19 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, bool ok = false; const char *ident; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_BOOLEAN) { + if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) { log_err(ctx, "Found constant of type %s where boolean was expected\n", - expr_value_type_to_string(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *set_rtrn = !!expr->value.ival; + *set_rtrn = expr->boolean.set; return true; case EXPR_IDENT: - ident = xkb_atom_text(ctx, expr->value.str); + ident = xkb_atom_text(ctx, expr->ident.ident); if (ident) { if (istreq(ident, "true") || istreq(ident, "yes") || @@ -154,14 +154,13 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, return true; } } - log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", - xkb_atom_text(ctx, expr->value.str)); + log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", ident); return false; case EXPR_FIELD_REF: log_err(ctx, "Default \"%s.%s\" of type boolean is unknown\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); return false; case EXPR_INVERT: @@ -178,11 +177,12 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, case EXPR_NEGATE: case EXPR_UNARY_PLUS: log_err(ctx, "%s of boolean values not permitted\n", - expr_op_type_to_string(expr->op)); + expr_op_type_to_string(expr->expr.op)); break; default: - log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", + expr->expr.op); break; } @@ -194,32 +194,28 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr, xkb_keycode_t *kc) { xkb_keycode_t leftRtrn, rightRtrn; - ExprDef *left, *right; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_INT) { + if (expr->expr.value_type != EXPR_TYPE_INT) { log_err(ctx, "Found constant of type %s where an int was expected\n", - expr_value_type_to_string(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *kc = expr->value.uval; + *kc = (xkb_keycode_t) expr->integer.ival; return true; case EXPR_ADD: case EXPR_SUBTRACT: case EXPR_MULTIPLY: case EXPR_DIVIDE: - left = expr->value.binary.left; - right = expr->value.binary.right; - - if (!ExprResolveKeyCode(ctx, left, &leftRtrn) || - !ExprResolveKeyCode(ctx, right, &rightRtrn)) + if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) || + !ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn)) return false; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_ADD: *kc = leftRtrn + rightRtrn; break; @@ -245,19 +241,18 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr, return true; case EXPR_NEGATE: - left = expr->value.child; - if (!ExprResolveKeyCode(ctx, left, &leftRtrn)) + if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn)) return false; *kc = ~leftRtrn; return true; case EXPR_UNARY_PLUS: - left = expr->value.child; - return ExprResolveKeyCode(ctx, left, kc); + return ExprResolveKeyCode(ctx, expr->unary.child, kc); default: - log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", + expr->expr.op); break; } @@ -284,25 +279,25 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr, unsigned u; ExprDef *left, *right; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_INT) { + if (expr->expr.value_type != EXPR_TYPE_INT) { log_err(ctx, "Found constant of type %s where an int was expected\n", - expr_value_type_to_string(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *val_rtrn = expr->value.ival; + *val_rtrn = expr->integer.ival; return true; case EXPR_IDENT: if (lookup) - ok = lookup(ctx, lookupPriv, expr->value.str, EXPR_TYPE_INT, &u); + ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u); if (!ok) log_err(ctx, "Identifier \"%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.str)); + xkb_atom_text(ctx, expr->ident.ident)); else *val_rtrn = (int) u; @@ -310,21 +305,21 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr, case EXPR_FIELD_REF: log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); return false; case EXPR_ADD: case EXPR_SUBTRACT: case EXPR_MULTIPLY: case EXPR_DIVIDE: - left = expr->value.binary.left; - right = expr->value.binary.right; + left = expr->binary.left; + right = expr->binary.right; if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) || !ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv)) return false; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_ADD: *val_rtrn = l + r; break; @@ -357,20 +352,21 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr, case EXPR_INVERT: case EXPR_NEGATE: - left = expr->value.child; + left = expr->unary.child; if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv)) return false; - *val_rtrn = (expr->op == EXPR_NEGATE ? -l : ~l); + *val_rtrn = (expr->expr.op == EXPR_NEGATE ? -l : ~l); return true; case EXPR_UNARY_PLUS: - left = expr->value.child; + left = expr->unary.child; return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup, lookupPriv); default: - log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", + expr->expr.op); break; } @@ -445,26 +441,26 @@ bool ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, xkb_atom_t *val_rtrn) { - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_STRING) { + if (expr->expr.value_type != EXPR_TYPE_STRING) { log_err(ctx, "Found constant of type %s, expected a string\n", - expr_value_type_to_string(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *val_rtrn = expr->value.str; + *val_rtrn = expr->string.str; return true; case EXPR_IDENT: log_err(ctx, "Identifier \"%s\" of type string not found\n", - xkb_atom_text(ctx, expr->value.str)); + xkb_atom_text(ctx, expr->ident.ident)); return false; case EXPR_FIELD_REF: log_err(ctx, "Default \"%s.%s\" of type string not found\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); return false; case EXPR_ADD: @@ -477,11 +473,12 @@ ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, case EXPR_NOT: case EXPR_UNARY_PLUS: log_err(ctx, "%s of strings not permitted\n", - expr_op_type_to_string(expr->op)); + expr_op_type_to_string(expr->expr.op)); return false; default: - log_wsgo(ctx, "Unknown operator %d in ResolveString\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveString\n", + expr->expr.op); break; } return false; @@ -491,16 +488,16 @@ bool ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, unsigned int *val_rtrn, const LookupEntry *values) { - if (expr->op != EXPR_IDENT) { + if (expr->expr.op != EXPR_IDENT) { log_err(ctx, "Found a %s where an enumerated value was expected\n", - expr_op_type_to_string(expr->op)); + expr_op_type_to_string(expr->expr.op)); return false; } - if (!SimpleLookup(ctx, values, expr->value.str, EXPR_TYPE_INT, + if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT, val_rtrn)) { log_err(ctx, "Illegal identifier %s; expected one of:\n", - xkb_atom_text(ctx, expr->value.str)); + xkb_atom_text(ctx, expr->ident.ident)); while (values && values->name) { log_err(ctx, "\t%s\n", values->name); @@ -523,29 +520,29 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, ExprDef *left, *right; const char *bogus = NULL; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_VALUE: - if (expr->value_type != EXPR_TYPE_INT) { + if (expr->expr.value_type != EXPR_TYPE_INT) { log_err(ctx, "Found constant of type %s where a mask was expected\n", - expr_value_type_to_string(expr->value_type)); + expr_value_type_to_string(expr->expr.value_type)); return false; } - *val_rtrn = (unsigned int) expr->value.ival; + *val_rtrn = (unsigned int) expr->integer.ival; return true; case EXPR_IDENT: - ok = lookup(ctx, lookupPriv, expr->value.str, EXPR_TYPE_INT, + ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, val_rtrn); if (!ok) log_err(ctx, "Identifier \"%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.str)); + xkb_atom_text(ctx, expr->ident.ident)); return ok; case EXPR_FIELD_REF: log_err(ctx, "Default \"%s.%s\" of type int is unknown\n", - xkb_atom_text(ctx, expr->value.field.element), - xkb_atom_text(ctx, expr->value.field.field)); + xkb_atom_text(ctx, expr->field_ref.element), + xkb_atom_text(ctx, expr->field_ref.field)); return false; case EXPR_ARRAY_REF: @@ -563,13 +560,13 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, case EXPR_SUBTRACT: case EXPR_MULTIPLY: case EXPR_DIVIDE: - left = expr->value.binary.left; - right = expr->value.binary.right; + left = expr->binary.left; + right = expr->binary.right; if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) || !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv)) return false; - switch (expr->op) { + switch (expr->expr.op) { case EXPR_ADD: *val_rtrn = l | r; break; @@ -579,7 +576,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, case EXPR_MULTIPLY: case EXPR_DIVIDE: log_err(ctx, "Cannot %s masks; Illegal operation ignored\n", - (expr->op == EXPR_DIVIDE ? "divide" : "multiply")); + (expr->expr.op == EXPR_DIVIDE ? "divide" : "multiply")); return false; default: break; @@ -592,7 +589,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, break; case EXPR_INVERT: - left = expr->value.child; + left = expr->unary.child; if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) return false; @@ -602,14 +599,15 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, case EXPR_UNARY_PLUS: case EXPR_NEGATE: case EXPR_NOT: - left = expr->value.child; + left = expr->unary.child; if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) log_err(ctx, "The %s operator cannot be used with a mask\n", - (expr->op == EXPR_NEGATE ? "-" : "!")); + (expr->expr.op == EXPR_NEGATE ? "-" : "!")); return false; default: - log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", expr->op); + log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", + expr->expr.op); break; } @@ -638,9 +636,8 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr, { int val; - if (expr->op == EXPR_IDENT) { - const char *str; - str = xkb_atom_text(ctx, expr->value.str); + if (expr->expr.op == EXPR_IDENT) { + const char *str = xkb_atom_text(ctx, expr->ident.ident); *sym_rtrn = xkb_keysym_from_name(str, 0); if (*sym_rtrn != XKB_KEY_NoSymbol) return true; @@ -652,7 +649,7 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr, if (val < 0 || val >= 10) return false; - *sym_rtrn = ((xkb_keysym_t) val) + '0'; + *sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val; return true; } @@ -661,16 +658,17 @@ ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def, enum mod_type mod_type, xkb_mod_index_t *ndx_rtrn) { xkb_mod_index_t ndx; - xkb_atom_t name = def->value.str; + xkb_atom_t name; - if (def->op != EXPR_IDENT) { + if (def->expr.op != EXPR_IDENT) { log_err(keymap->ctx, "Cannot resolve virtual modifier: " "found %s where a virtual modifier name was expected\n", - expr_op_type_to_string(def->op)); + expr_op_type_to_string(def->expr.op)); return false; } + name = def->ident.ident; ndx = ModNameToIndex(keymap, name, mod_type); if (ndx == XKB_MOD_INVALID) { log_err(keymap->ctx, diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/include.c b/src/3rdparty/xkbcommon/src/xkbcomp/include.c index b4a4014635..dc3f1e49bd 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/include.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/include.c @@ -199,17 +199,34 @@ FindFileInXkbPath(struct xkb_context *ctx, const char *name, { unsigned int i; FILE *file = NULL; - char buf[PATH_MAX]; + char *buf = NULL; const char *typeDir; + size_t buf_size = 0, typeDirLen, name_len; typeDir = DirectoryForInclude(type); + typeDirLen = strlen(typeDir); + name_len = strlen(name); for (i = 0; i < xkb_context_num_include_paths(ctx); i++) { - int ret = snprintf(buf, sizeof(buf), "%s/%s/%s", - xkb_context_include_path_get(ctx, i), - typeDir, name); - if (ret >= (ssize_t) sizeof(buf)) { - log_err(ctx, "File name (%s/%s/%s) too long\n", + size_t new_buf_size = strlen(xkb_context_include_path_get(ctx, i)) + + typeDirLen + name_len + 3; + int ret; + if (new_buf_size > buf_size) { + void *buf_new = realloc(buf, new_buf_size); + if (buf_new) { + buf_size = new_buf_size; + buf = buf_new; + } else { + log_err(ctx, "Cannot realloc for name (%s/%s/%s)\n", + xkb_context_include_path_get(ctx, i), typeDir, name); + continue; + } + } + ret = snprintf(buf, buf_size, "%s/%s/%s", + xkb_context_include_path_get(ctx, i), + typeDir, name); + if (ret < 0) { + log_err(ctx, "snprintf error (%s/%s/%s)\n", xkb_context_include_path_get(ctx, i), typeDir, name); continue; } @@ -242,11 +259,14 @@ FindFileInXkbPath(struct xkb_context *ctx, const char *name, xkb_context_failed_include_path_get(ctx, i)); } + free(buf); return NULL; } if (pathRtrn) - *pathRtrn = strdup(buf); + *pathRtrn = buf; + else + free(buf); return file; } @@ -275,7 +295,7 @@ ProcessIncludeFile(struct xkb_context *ctx, IncludeStmt *stmt, if (xkb_file->file_type != file_type) { log_err(ctx, - "Include file wrong type (expected %s, got %s); " + "Include file of wrong type (expected %s, got %s); " "Include file \"%s\" ignored\n", xkb_file_type_to_string(file_type), xkb_file_type_to_string(xkb_file->file_type), stmt->file); diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c b/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c index edc54c94f3..59916b7266 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c @@ -231,7 +231,10 @@ InitKeyNamesInfo(KeyNamesInfo *info, struct xkb_context *ctx) { memset(info, 0, sizeof(*info)); info->ctx = ctx; - info->min_key_code = XKB_KEYCODE_MAX; + info->min_key_code = XKB_KEYCODE_INVALID; +#if XKB_KEYCODE_INVALID < XKB_KEYCODE_MAX +#error "Hey, you can't be changing stuff like that." +#endif } static xkb_keycode_t @@ -604,16 +607,28 @@ CopyKeyNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info) unsigned i; keymap->keycodes_section_name = strdup_safe(info->name); + XkbEscapeMapName(keymap->keycodes_section_name); - keymap->min_key_code = info->min_key_code; - keymap->max_key_code = info->max_key_code; + if (info->min_key_code != XKB_KEYCODE_INVALID) { + keymap->min_key_code = info->min_key_code; + keymap->max_key_code = info->max_key_code; + } + else { + /* + * If the keymap has no keys, let's just use the safest pair + * we know. + */ + keymap->min_key_code = 8; + keymap->max_key_code = 255; + } - /* Copy key names. */ - keymap->keys = calloc(info->max_key_code + 1, sizeof(*keymap->keys)); - for (kc = info->min_key_code; kc <= info->max_key_code; kc++) { + keymap->keys = calloc(keymap->max_key_code + 1, sizeof(*keymap->keys)); + for (kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++) keymap->keys[kc].keycode = kc; + + /* Copy key names. */ + for (kc = info->min_key_code; kc <= info->max_key_code; kc++) keymap->keys[kc].name = darray_item(info->key_names, kc); - } /* * Do some sanity checking on the aliases. We can't do it before diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c b/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c index 034a8c1af3..6b4c266ec0 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c @@ -157,17 +157,24 @@ write_keycodes(struct xkb_keymap *keymap, struct buf *buf) else write_buf(buf, "xkb_keycodes {\n"); + /* xkbcomp and X11 really want to see keymaps with a minimum of 8, and + * a maximum of at least 255, else XWayland really starts hating life. + * If this is a problem and people really need strictly bounded keymaps, + * we should probably control this with a flag. */ + write_buf(buf, "\tminimum = %u;\n", min(keymap->min_key_code, 8)); + write_buf(buf, "\tmaximum = %u;\n", max(keymap->max_key_code, 255)); + xkb_foreach_key(key, keymap) { if (key->name == XKB_ATOM_NONE) continue; - write_buf(buf, "\t%-20s = %d;\n", + write_buf(buf, "\t%-20s = %u;\n", KeyNameText(keymap->ctx, key->name), key->keycode); } darray_enumerate(idx, led, keymap->leds) if (led->name != XKB_ATOM_NONE) - write_buf(buf, "\tindicator %d = \"%s\";\n", + write_buf(buf, "\tindicator %u = \"%s\";\n", idx + 1, xkb_atom_text(keymap->ctx, led->name)); @@ -212,7 +219,7 @@ write_types(struct xkb_keymap *keymap, struct buf *buf) continue; str = ModMaskText(keymap, entry->mods.mods); - write_buf(buf, "\t\tmap[%s]= Level%d;\n", + write_buf(buf, "\t\tmap[%s]= Level%u;\n", str, entry->level + 1); if (entry->preserve.mods) @@ -222,7 +229,7 @@ write_types(struct xkb_keymap *keymap, struct buf *buf) for (xkb_level_index_t n = 0; n < type->num_levels; n++) if (type->level_names[n]) - write_buf(buf, "\t\tlevel_name[Level%d]= \"%s\";\n", n + 1, + write_buf(buf, "\t\tlevel_name[Level%u]= \"%s\";\n", n + 1, xkb_atom_text(keymap->ctx, type->level_names[n])); write_buf(buf, "\t};\n"); @@ -409,7 +416,6 @@ write_action(struct xkb_keymap *keymap, struct buf *buf, static bool write_compat(struct xkb_keymap *keymap, struct buf *buf) { - const struct xkb_sym_interpret *si; const struct xkb_led *led; if (keymap->compat_section_name) @@ -423,7 +429,9 @@ write_compat(struct xkb_keymap *keymap, struct buf *buf) write_buf(buf, "\tinterpret.useModMapMods= AnyLevel;\n"); write_buf(buf, "\tinterpret.repeat= False;\n"); - darray_foreach(si, keymap->sym_interprets) { + for (int i = 0; i < keymap->num_sym_interprets; i++) { + const struct xkb_sym_interpret *si = &keymap->sym_interprets[i]; + write_buf(buf, "\tinterpret %s+%s(%s) {\n", si->sym ? KeysymText(keymap->ctx, si->sym) : "Any", SIMatchText(si->match), @@ -610,7 +618,7 @@ write_symbols(struct xkb_keymap *keymap, struct buf *buf) for (group = 0; group < keymap->num_group_names; group++) if (keymap->group_names[group]) write_buf(buf, - "\tname[group%d]=\"%s\";\n", group + 1, + "\tname[group%u]=\"%s\";\n", group + 1, xkb_atom_text(keymap->ctx, keymap->group_names[group])); if (group > 0) write_buf(buf, "\n"); diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c b/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c index bed3930be9..549cf05da6 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c @@ -78,7 +78,6 @@ static const struct xkb_sym_interpret * FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key, xkb_layout_index_t group, xkb_level_index_t level) { - const struct xkb_sym_interpret *interp; const xkb_keysym_t *syms; int num_syms; @@ -93,7 +92,9 @@ FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key, * sym_interprets array from the most specific to the least specific, * such that when we find a match we return immediately. */ - darray_foreach(interp, keymap->sym_interprets) { + for (int i = 0; i < keymap->num_sym_interprets; i++) { + const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i]; + xkb_mod_mask_t mods; bool found = false; @@ -224,28 +225,6 @@ UpdateDerivedKeymapFields(struct xkb_keymap *keymap) return true; } -static bool -UpdateBuiltinKeymapFields(struct xkb_keymap *keymap) -{ - struct xkb_context *ctx = keymap->ctx; - - /* - * Add predefined (AKA real, core, X11) modifiers. - * The order is important! - */ - darray_appends_t(keymap->mods, struct xkb_mod, - { .name = xkb_atom_intern(ctx, "Shift"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Lock"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Control"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Mod1"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Mod2"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Mod3"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Mod4"), .type = MOD_REAL }, - { .name = xkb_atom_intern(ctx, "Mod5"), .type = MOD_REAL }); - - return true; -} - typedef bool (*compile_file_fn)(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge); @@ -311,9 +290,6 @@ CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge) if (!ok) return false; - if (!UpdateBuiltinKeymapFields(keymap)) - return false; - /* Compile sections. */ for (type = FIRST_KEYMAP_FILE_TYPE; type <= LAST_KEYMAP_FILE_TYPE; diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keywords.c b/src/3rdparty/xkbcommon/src/xkbcomp/keywords.c new file mode 100644 index 0000000000..c19d66ffde --- /dev/null +++ b/src/3rdparty/xkbcommon/src/xkbcomp/keywords.c @@ -0,0 +1,349 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf */ +/* Computed positions: -k'1-2,5' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + + +#include "xkbcomp-priv.h" +#include "parser-priv.h" + +static unsigned int +keyword_gperf_hash(const char *str, unsigned int len); + +static const struct keyword_tok * +keyword_gperf_lookup(const char *str, unsigned int len); +struct keyword_tok { int name; int tok; }; +#include +/* maximum key range = 70, duplicates = 0 */ + +#ifndef GPERF_DOWNCASE +#define GPERF_DOWNCASE 1 +static unsigned char gperf_downcase[256] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 + }; +#endif + +#ifndef GPERF_CASE_STRCMP +#define GPERF_CASE_STRCMP 1 +static int +gperf_case_strcmp (register const char *s1, register const char *s2) +{ + for (;;) + { + unsigned char c1 = gperf_downcase[(unsigned char)*s1++]; + unsigned char c2 = gperf_downcase[(unsigned char)*s2++]; + if (c1 != 0 && c1 == c2) + continue; + return (int)c1 - (int)c2; + } +} +#endif + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +keyword_gperf_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 0, 73, 5, 36, 0, + 10, 1, 15, 15, 73, 0, 10, 20, 35, 20, + 50, 73, 10, 10, 5, 0, 15, 73, 0, 15, + 73, 73, 73, 73, 73, 73, 73, 0, 73, 5, + 36, 0, 10, 1, 15, 15, 73, 0, 10, 20, + 35, 20, 50, 73, 10, 10, 5, 0, 15, 73, + 0, 15, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[4]]; + /*FALLTHROUGH*/ + case 4: + case 3: + case 2: + hval += asso_values[(unsigned char)str[1]]; + /*FALLTHROUGH*/ + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval; +} + +struct stringpool_t + { + char stringpool_str3[sizeof("key")]; + char stringpool_str4[sizeof("keys")]; + char stringpool_str7[sizeof("augment")]; + char stringpool_str9[sizeof("text")]; + char stringpool_str10[sizeof("xkb_keymap")]; + char stringpool_str11[sizeof("keypad_keys")]; + char stringpool_str12[sizeof("xkb_keycodes")]; + char stringpool_str13[sizeof("xkb_geometry")]; + char stringpool_str14[sizeof("xkb_types")]; + char stringpool_str15[sizeof("xkb_compat")]; + char stringpool_str17[sizeof("replace")]; + char stringpool_str19[sizeof("xkb_compat_map")]; + char stringpool_str20[sizeof("xkb_layout")]; + char stringpool_str21[sizeof("xkb_symbols")]; + char stringpool_str22[sizeof("xkb_compatibility")]; + char stringpool_str23[sizeof("xkb_semantics")]; + char stringpool_str24[sizeof("type")]; + char stringpool_str25[sizeof("alias")]; + char stringpool_str26[sizeof("xkb_compatibility_map")]; + char stringpool_str27[sizeof("alphanumeric_keys")]; + char stringpool_str28[sizeof("function_keys")]; + char stringpool_str29[sizeof("alternate")]; + char stringpool_str30[sizeof("shape")]; + char stringpool_str31[sizeof("action")]; + char stringpool_str32[sizeof("section")]; + char stringpool_str33[sizeof("row")]; + char stringpool_str34[sizeof("logo")]; + char stringpool_str35[sizeof("alternate_group")]; + char stringpool_str36[sizeof("hidden")]; + char stringpool_str37[sizeof("virtual")]; + char stringpool_str42[sizeof("outline")]; + char stringpool_str43[sizeof("default")]; + char stringpool_str46[sizeof("modmap")]; + char stringpool_str47[sizeof("virtual_modifiers")]; + char stringpool_str52[sizeof("overlay")]; + char stringpool_str53[sizeof("override")]; + char stringpool_str57[sizeof("include")]; + char stringpool_str62[sizeof("modifier_map")]; + char stringpool_str63[sizeof("modifier_keys")]; + char stringpool_str64[sizeof("indicator")]; + char stringpool_str66[sizeof("group")]; + char stringpool_str67[sizeof("mod_map")]; + char stringpool_str69[sizeof("interpret")]; + char stringpool_str71[sizeof("solid")]; + char stringpool_str72[sizeof("partial")]; + }; +static const struct stringpool_t stringpool_contents = + { + "key", + "keys", + "augment", + "text", + "xkb_keymap", + "keypad_keys", + "xkb_keycodes", + "xkb_geometry", + "xkb_types", + "xkb_compat", + "replace", + "xkb_compat_map", + "xkb_layout", + "xkb_symbols", + "xkb_compatibility", + "xkb_semantics", + "type", + "alias", + "xkb_compatibility_map", + "alphanumeric_keys", + "function_keys", + "alternate", + "shape", + "action", + "section", + "row", + "logo", + "alternate_group", + "hidden", + "virtual", + "outline", + "default", + "modmap", + "virtual_modifiers", + "overlay", + "override", + "include", + "modifier_map", + "modifier_keys", + "indicator", + "group", + "mod_map", + "interpret", + "solid", + "partial" + }; +#define stringpool ((const char *) &stringpool_contents) +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct keyword_tok * +keyword_gperf_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 45, + MIN_WORD_LENGTH = 3, + MAX_WORD_LENGTH = 21, + MIN_HASH_VALUE = 3, + MAX_HASH_VALUE = 72 + }; + + static const struct keyword_tok wordlist[] = + { + {-1}, {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str3, KEY}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str4, KEYS}, + {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, AUGMENT}, + {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, TEXT}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, XKB_KEYMAP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, KEYPAD_KEYS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, XKB_KEYCODES}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, XKB_GEOMETRY}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, XKB_TYPES}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, XKB_COMPATMAP}, + {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, REPLACE}, + {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, XKB_COMPATMAP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, XKB_LAYOUT}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, XKB_SYMBOLS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, XKB_COMPATMAP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, XKB_SEMANTICS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, TYPE}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, ALIAS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, XKB_COMPATMAP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, ALPHANUMERIC_KEYS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str28, FUNCTION_KEYS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, ALTERNATE}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, SHAPE}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, ACTION_TOK}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str32, SECTION}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, ROW}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, LOGO}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, ALTERNATE_GROUP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str36, HIDDEN}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str37, VIRTUAL}, + {-1}, {-1}, {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str42, OUTLINE}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str43, DEFAULT}, + {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str46, MODIFIER_MAP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str47, VIRTUAL_MODS}, + {-1}, {-1}, {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str52, OVERLAY}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str53, OVERRIDE}, + {-1}, {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str57, INCLUDE}, + {-1}, {-1}, {-1}, {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str62, MODIFIER_MAP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str63, MODIFIER_KEYS}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str64, INDICATOR}, + {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str66, GROUP}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str67, MODIFIER_MAP}, + {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str69, INTERPRET}, + {-1}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str71, SOLID}, + {(int)(long)&((struct stringpool_t *)0)->stringpool_str72, PARTIAL} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = keyword_gperf_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + stringpool; + + if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s)) + return &wordlist[key]; + } + } + } + return 0; +} + + +int +keyword_to_token(const char *string) +{ + const struct keyword_tok *kt; + kt = keyword_gperf_lookup(string, strlen(string)); + if (!kt) + return -1; + return kt->tok; +} diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h b/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h index 2e02db66a8..05e725eb00 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h +++ b/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h @@ -27,21 +27,24 @@ #ifndef XKBCOMP_PARSER_PRIV_H #define XKBCOMP_PARSER_PRIV_H -struct scanner_extra; +struct scanner; struct parser_param; -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic push #include "parser.h" -#pragma GCC diagnostic pop + +int +scanner_error(struct scanner *scanner, const char *msg); void -scanner_error(YYLTYPE *loc, void *scanner, const char *msg); +scanner_warn(struct scanner *s, const char *msg); int -_xkbcommon_lex(YYSTYPE *val, YYLTYPE *loc, void *scanner); +_xkbcommon_lex(YYSTYPE *yylval, struct scanner *scanner); XkbFile * parse(struct xkb_context *ctx, void *scanner, const char *map); +int +keyword_to_token(const char *string); + #endif diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/parser.c b/src/3rdparty/xkbcommon/src/xkbcomp/parser.c index e1280e9180..26bbf30be8 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/parser.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/parser.c @@ -59,7 +59,7 @@ #define YYPULL 1 /* Using locations. */ -#define YYLSP_NEEDED 1 +#define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse _xkbcommon_parse @@ -69,12 +69,12 @@ #define yychar _xkbcommon_char #define yydebug _xkbcommon_debug #define yynerrs _xkbcommon_nerrs -#define yylloc _xkbcommon_lloc + /* Copy the first part of user declarations. */ /* Line 268 of yacc.c */ -#line 27 "parser.y" +#line 33 "parser.y" #include "xkbcomp-priv.h" #include "ast-build.h" @@ -88,16 +88,52 @@ struct parser_param { }; static void -_xkbcommon_error(struct YYLTYPE *loc, struct parser_param *param, const char *msg) +parser_error(struct parser_param *param, const char *msg) { - scanner_error(loc, param->scanner, msg); + scanner_error(param->scanner, msg); +} + +static void +parser_warn(struct parser_param *param, const char *msg) +{ + scanner_warn(param->scanner, msg); +} + +static void +_xkbcommon_error(struct parser_param *param, const char *msg) +{ + parser_error(param, msg); +} + +static bool +resolve_keysym(const char *str, xkb_keysym_t *sym_rtrn) +{ + xkb_keysym_t sym; + + if (!str || istreq(str, "any") || istreq(str, "nosymbol")) { + *sym_rtrn = XKB_KEY_NoSymbol; + return true; + } + + if (istreq(str, "none") || istreq(str, "voidsymbol")) { + *sym_rtrn = XKB_KEY_VoidSymbol; + return true; + } + + sym = xkb_keysym_from_name(str, XKB_KEYSYM_NO_FLAGS); + if (sym != XKB_KEY_NoSymbol) { + *sym_rtrn = sym; + return true; + } + + return false; } #define scanner param->scanner /* Line 268 of yacc.c */ -#line 101 "src/xkbcomp/parser.c" +#line 137 "src/xkbcomp/parser.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -262,16 +298,16 @@ typedef union YYSTYPE { /* Line 293 of yacc.c */ -#line 127 "parser.y" +#line 167 "parser.y" int ival; - unsigned uval; int64_t num; enum xkb_file_type file_type; char *str; xkb_atom_t sval; enum merge_mode merge; enum xkb_map_flags mapFlags; + xkb_keysym_t keysym; ParseCommon *any; ExprDef *expr; VarDef *var; @@ -291,32 +327,19 @@ typedef union YYSTYPE /* Line 293 of yacc.c */ -#line 295 "src/xkbcomp/parser.c" +#line 331 "src/xkbcomp/parser.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - /* Copy the second part of user declarations. */ /* Line 343 of yacc.c */ -#line 320 "src/xkbcomp/parser.c" +#line 343 "src/xkbcomp/parser.c" #ifdef short # undef short @@ -474,15 +497,13 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ - || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ - && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; - YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ @@ -491,8 +512,8 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAXIMUM) + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 @@ -677,25 +698,25 @@ static const yytype_int16 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 198, 198, 200, 202, 206, 212, 213, 214, 217, - 224, 228, 243, 244, 245, 246, 247, 250, 251, 254, - 255, 258, 259, 260, 261, 262, 263, 264, 265, 268, - 270, 273, 278, 283, 288, 293, 298, 303, 308, 313, - 318, 323, 328, 329, 330, 331, 338, 340, 342, 346, - 350, 354, 358, 360, 364, 366, 370, 376, 378, 382, - 384, 388, 394, 400, 402, 404, 407, 408, 409, 410, - 411, 414, 416, 420, 424, 428, 432, 434, 438, 440, - 444, 448, 449, 452, 454, 456, 458, 460, 464, 465, - 468, 469, 473, 474, 477, 479, 483, 487, 488, 491, - 494, 496, 500, 502, 504, 508, 510, 514, 518, 522, - 523, 524, 525, 528, 529, 532, 534, 536, 538, 540, - 542, 544, 546, 548, 550, 552, 556, 557, 560, 561, - 562, 563, 564, 574, 575, 578, 580, 584, 586, 588, - 590, 592, 594, 598, 600, 602, 604, 606, 608, 610, - 612, 616, 618, 622, 626, 633, 641, 650, 661, 668, - 675, 679, 688, 689, 692, 694, 696, 698, 702, 706, - 707, 708, 722, 723, 726, 727, 730, 733, 736, 739, - 740, 743, 746, 747, 750 + 0, 238, 238, 240, 242, 246, 252, 253, 254, 257, + 264, 268, 283, 284, 285, 286, 287, 290, 291, 294, + 295, 298, 299, 300, 301, 302, 303, 304, 305, 308, + 310, 313, 318, 323, 328, 333, 338, 343, 348, 353, + 358, 363, 368, 369, 370, 371, 378, 380, 382, 386, + 390, 394, 398, 400, 404, 406, 410, 416, 418, 422, + 424, 428, 434, 440, 442, 444, 447, 448, 449, 450, + 451, 454, 456, 460, 464, 468, 472, 474, 478, 480, + 484, 488, 489, 492, 494, 496, 498, 500, 504, 505, + 508, 509, 513, 514, 517, 519, 523, 527, 528, 531, + 534, 536, 540, 542, 544, 548, 550, 554, 558, 562, + 563, 564, 565, 568, 569, 572, 574, 576, 578, 580, + 582, 584, 586, 588, 590, 592, 596, 597, 600, 601, + 602, 603, 604, 614, 615, 618, 620, 624, 626, 628, + 630, 632, 634, 638, 640, 642, 644, 646, 648, 650, + 652, 656, 658, 662, 666, 668, 670, 672, 676, 678, + 680, 682, 686, 687, 690, 692, 694, 696, 700, 704, + 710, 711, 725, 726, 729, 730, 733, 736, 739, 742, + 743, 746, 749, 750, 753 }; #endif @@ -1148,7 +1169,7 @@ do \ } \ else \ { \ - yyerror (&yylloc, param, YY_("syntax error: cannot back up")); \ + yyerror (param, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -1184,28 +1205,19 @@ while (YYID (0)) #endif -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ +/* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +# define YYLEX yylex (&yylval, YYLEX_PARAM) #else -# define YYLEX yylex (&yylval, &yylloc, scanner) +# define YYLEX yylex (&yylval, scanner) #endif /* Enable debugging if requested. */ @@ -1228,7 +1240,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, Location, param); \ + Type, Value, param); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -1242,20 +1254,18 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_param *param) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_param *param) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, param) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, param) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; struct parser_param *param; #endif { if (!yyvaluep) return; - YYUSE (yylocationp); YYUSE (param); # ifdef YYPRINT if (yytype < YYNTOKENS) @@ -1278,14 +1288,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, param) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct parser_param *param) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_param *param) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, param) +yy_symbol_print (yyoutput, yytype, yyvaluep, param) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; struct parser_param *param; #endif { @@ -1294,9 +1303,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, param) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, param); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, param); YYFPRINTF (yyoutput, ")"); } @@ -1339,12 +1346,11 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct parser_param *param) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, struct parser_param *param) #else static void -yy_reduce_print (yyvsp, yylsp, yyrule, param) +yy_reduce_print (yyvsp, yyrule, param) YYSTYPE *yyvsp; - YYLTYPE *yylsp; int yyrule; struct parser_param *param; #endif @@ -1360,7 +1366,7 @@ yy_reduce_print (yyvsp, yylsp, yyrule, param) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) , param); + , param); YYFPRINTF (stderr, "\n"); } } @@ -1368,7 +1374,7 @@ yy_reduce_print (yyvsp, yylsp, yyrule, param) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule, param); \ + yy_reduce_print (yyvsp, Rule, param); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1645,19 +1651,17 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct parser_param *param) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct parser_param *param) #else static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp, param) +yydestruct (yymsg, yytype, yyvaluep, param) const char *yymsg; int yytype; YYSTYPE *yyvaluep; - YYLTYPE *yylocationp; struct parser_param *param; #endif { YYUSE (yyvaluep); - YYUSE (yylocationp); YYUSE (param); if (!yymsg) @@ -1721,9 +1725,6 @@ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; -/* Location data for the lookahead symbol. */ -YYLTYPE yylloc; - /* Number of syntax errors so far. */ int yynerrs; @@ -1734,7 +1735,6 @@ YYLTYPE yylloc; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. - `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ @@ -1749,14 +1749,6 @@ YYLTYPE yylloc; YYSTYPE *yyvs; YYSTYPE *yyvsp; - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls; - YYLTYPE *yylsp; - - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[3]; - YYSIZE_T yystacksize; int yyn; @@ -1766,7 +1758,6 @@ YYLTYPE yylloc; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; - YYLTYPE yyloc; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ @@ -1775,7 +1766,7 @@ YYLTYPE yylloc; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ @@ -1784,7 +1775,6 @@ YYLTYPE yylloc; yytoken = 0; yyss = yyssa; yyvs = yyvsa; - yyls = yylsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1800,13 +1790,6 @@ YYLTYPE yylloc; The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; - yylsp = yyls; - -#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - /* Initialize the default location before parsing starts. */ - yylloc.first_line = yylloc.last_line = 1; - yylloc.first_column = yylloc.last_column = 1; -#endif goto yysetstate; @@ -1833,7 +1816,6 @@ YYLTYPE yylloc; memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; - YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a @@ -1842,10 +1824,8 @@ YYLTYPE yylloc; yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), &yystacksize); - yyls = yyls1; yyss = yyss1; yyvs = yyvs1; } @@ -1868,7 +1848,6 @@ YYLTYPE yylloc; goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); - YYSTACK_RELOCATE (yyls_alloc, yyls); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1878,7 +1857,6 @@ YYLTYPE yylloc; yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1954,7 +1932,7 @@ yybackup: yystate = yyn; *++yyvsp = yylval; - *++yylsp = yylloc; + goto yynewstate; @@ -1985,64 +1963,63 @@ yyreduce: GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: /* Line 1806 of yacc.c */ -#line 199 "parser.y" +#line 239 "parser.y" { (yyval.file) = param->rtrn = (yyvsp[(1) - (1)].file); param->more_maps = true; } break; case 3: /* Line 1806 of yacc.c */ -#line 201 "parser.y" +#line 241 "parser.y" { (yyval.file) = param->rtrn = (yyvsp[(1) - (1)].file); param->more_maps = true; YYACCEPT; } break; case 4: /* Line 1806 of yacc.c */ -#line 203 "parser.y" +#line 243 "parser.y" { (yyval.file) = param->rtrn = NULL; param->more_maps = false; } break; case 5: /* Line 1806 of yacc.c */ -#line 209 "parser.y" +#line 249 "parser.y" { (yyval.file) = XkbFileCreate(param->ctx, (yyvsp[(2) - (7)].file_type), (yyvsp[(3) - (7)].str), &(yyvsp[(5) - (7)].file)->common, (yyvsp[(1) - (7)].mapFlags)); } break; case 6: /* Line 1806 of yacc.c */ -#line 212 "parser.y" +#line 252 "parser.y" { (yyval.file_type) = FILE_TYPE_KEYMAP; } break; case 7: /* Line 1806 of yacc.c */ -#line 213 "parser.y" +#line 253 "parser.y" { (yyval.file_type) = FILE_TYPE_KEYMAP; } break; case 8: /* Line 1806 of yacc.c */ -#line 214 "parser.y" +#line 254 "parser.y" { (yyval.file_type) = FILE_TYPE_KEYMAP; } break; case 9: /* Line 1806 of yacc.c */ -#line 218 "parser.y" +#line 258 "parser.y" { if (!(yyvsp[(2) - (2)].file)) (yyval.file) = (yyvsp[(1) - (2)].file); @@ -2054,14 +2031,14 @@ yyreduce: case 10: /* Line 1806 of yacc.c */ -#line 225 "parser.y" +#line 265 "parser.y" { (yyval.file) = (yyvsp[(1) - (1)].file); } break; case 11: /* Line 1806 of yacc.c */ -#line 231 "parser.y" +#line 271 "parser.y" { if ((yyvsp[(2) - (7)].file_type) == FILE_TYPE_GEOMETRY) { free((yyvsp[(3) - (7)].str)); @@ -2077,140 +2054,140 @@ yyreduce: case 12: /* Line 1806 of yacc.c */ -#line 243 "parser.y" +#line 283 "parser.y" { (yyval.file_type) = FILE_TYPE_KEYCODES; } break; case 13: /* Line 1806 of yacc.c */ -#line 244 "parser.y" +#line 284 "parser.y" { (yyval.file_type) = FILE_TYPE_TYPES; } break; case 14: /* Line 1806 of yacc.c */ -#line 245 "parser.y" +#line 285 "parser.y" { (yyval.file_type) = FILE_TYPE_COMPAT; } break; case 15: /* Line 1806 of yacc.c */ -#line 246 "parser.y" +#line 286 "parser.y" { (yyval.file_type) = FILE_TYPE_SYMBOLS; } break; case 16: /* Line 1806 of yacc.c */ -#line 247 "parser.y" +#line 287 "parser.y" { (yyval.file_type) = FILE_TYPE_GEOMETRY; } break; case 17: /* Line 1806 of yacc.c */ -#line 250 "parser.y" +#line 290 "parser.y" { (yyval.mapFlags) = (yyvsp[(1) - (1)].mapFlags); } break; case 18: /* Line 1806 of yacc.c */ -#line 251 "parser.y" +#line 291 "parser.y" { (yyval.mapFlags) = 0; } break; case 19: /* Line 1806 of yacc.c */ -#line 254 "parser.y" +#line 294 "parser.y" { (yyval.mapFlags) = ((yyvsp[(1) - (2)].mapFlags) | (yyvsp[(2) - (2)].mapFlags)); } break; case 20: /* Line 1806 of yacc.c */ -#line 255 "parser.y" +#line 295 "parser.y" { (yyval.mapFlags) = (yyvsp[(1) - (1)].mapFlags); } break; case 21: /* Line 1806 of yacc.c */ -#line 258 "parser.y" +#line 298 "parser.y" { (yyval.mapFlags) = MAP_IS_PARTIAL; } break; case 22: /* Line 1806 of yacc.c */ -#line 259 "parser.y" +#line 299 "parser.y" { (yyval.mapFlags) = MAP_IS_DEFAULT; } break; case 23: /* Line 1806 of yacc.c */ -#line 260 "parser.y" +#line 300 "parser.y" { (yyval.mapFlags) = MAP_IS_HIDDEN; } break; case 24: /* Line 1806 of yacc.c */ -#line 261 "parser.y" +#line 301 "parser.y" { (yyval.mapFlags) = MAP_HAS_ALPHANUMERIC; } break; case 25: /* Line 1806 of yacc.c */ -#line 262 "parser.y" +#line 302 "parser.y" { (yyval.mapFlags) = MAP_HAS_MODIFIER; } break; case 26: /* Line 1806 of yacc.c */ -#line 263 "parser.y" +#line 303 "parser.y" { (yyval.mapFlags) = MAP_HAS_KEYPAD; } break; case 27: /* Line 1806 of yacc.c */ -#line 264 "parser.y" +#line 304 "parser.y" { (yyval.mapFlags) = MAP_HAS_FN; } break; case 28: /* Line 1806 of yacc.c */ -#line 265 "parser.y" +#line 305 "parser.y" { (yyval.mapFlags) = MAP_IS_ALTGR; } break; case 29: /* Line 1806 of yacc.c */ -#line 269 "parser.y" +#line 309 "parser.y" { (yyval.any) = AppendStmt((yyvsp[(1) - (2)].any), (yyvsp[(2) - (2)].any)); } break; case 30: /* Line 1806 of yacc.c */ -#line 270 "parser.y" +#line 310 "parser.y" { (yyval.any) = NULL; } break; case 31: /* Line 1806 of yacc.c */ -#line 274 "parser.y" +#line 314 "parser.y" { (yyvsp[(2) - (2)].var)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].var)->common; @@ -2220,7 +2197,7 @@ yyreduce: case 32: /* Line 1806 of yacc.c */ -#line 279 "parser.y" +#line 319 "parser.y" { (yyvsp[(2) - (2)].vmod)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].vmod)->common; @@ -2230,7 +2207,7 @@ yyreduce: case 33: /* Line 1806 of yacc.c */ -#line 284 "parser.y" +#line 324 "parser.y" { (yyvsp[(2) - (2)].interp)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].interp)->common; @@ -2240,7 +2217,7 @@ yyreduce: case 34: /* Line 1806 of yacc.c */ -#line 289 "parser.y" +#line 329 "parser.y" { (yyvsp[(2) - (2)].keyCode)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].keyCode)->common; @@ -2250,7 +2227,7 @@ yyreduce: case 35: /* Line 1806 of yacc.c */ -#line 294 "parser.y" +#line 334 "parser.y" { (yyvsp[(2) - (2)].keyAlias)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].keyAlias)->common; @@ -2260,7 +2237,7 @@ yyreduce: case 36: /* Line 1806 of yacc.c */ -#line 299 "parser.y" +#line 339 "parser.y" { (yyvsp[(2) - (2)].keyType)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].keyType)->common; @@ -2270,7 +2247,7 @@ yyreduce: case 37: /* Line 1806 of yacc.c */ -#line 304 "parser.y" +#line 344 "parser.y" { (yyvsp[(2) - (2)].syms)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].syms)->common; @@ -2280,7 +2257,7 @@ yyreduce: case 38: /* Line 1806 of yacc.c */ -#line 309 "parser.y" +#line 349 "parser.y" { (yyvsp[(2) - (2)].modMask)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].modMask)->common; @@ -2290,7 +2267,7 @@ yyreduce: case 39: /* Line 1806 of yacc.c */ -#line 314 "parser.y" +#line 354 "parser.y" { (yyvsp[(2) - (2)].groupCompat)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].groupCompat)->common; @@ -2300,7 +2277,7 @@ yyreduce: case 40: /* Line 1806 of yacc.c */ -#line 319 "parser.y" +#line 359 "parser.y" { (yyvsp[(2) - (2)].ledMap)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].ledMap)->common; @@ -2310,7 +2287,7 @@ yyreduce: case 41: /* Line 1806 of yacc.c */ -#line 324 "parser.y" +#line 364 "parser.y" { (yyvsp[(2) - (2)].ledName)->merge = (yyvsp[(1) - (2)].merge); (yyval.any) = &(yyvsp[(2) - (2)].ledName)->common; @@ -2320,28 +2297,28 @@ yyreduce: case 42: /* Line 1806 of yacc.c */ -#line 328 "parser.y" +#line 368 "parser.y" { (yyval.any) = NULL; } break; case 43: /* Line 1806 of yacc.c */ -#line 329 "parser.y" +#line 369 "parser.y" { (yyval.any) = NULL; } break; case 44: /* Line 1806 of yacc.c */ -#line 330 "parser.y" +#line 370 "parser.y" { (yyval.any) = NULL; } break; case 45: /* Line 1806 of yacc.c */ -#line 332 "parser.y" +#line 372 "parser.y" { (yyval.any) = &IncludeCreate(param->ctx, (yyvsp[(2) - (2)].str), (yyvsp[(1) - (2)].merge))->common; free((yyvsp[(2) - (2)].str)); @@ -2351,609 +2328,609 @@ yyreduce: case 46: /* Line 1806 of yacc.c */ -#line 339 "parser.y" +#line 379 "parser.y" { (yyval.var) = VarCreate((yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); } break; case 47: /* Line 1806 of yacc.c */ -#line 341 "parser.y" - { (yyval.var) = BoolVarCreate((yyvsp[(1) - (2)].sval), 1); } +#line 381 "parser.y" + { (yyval.var) = BoolVarCreate((yyvsp[(1) - (2)].sval), true); } break; case 48: /* Line 1806 of yacc.c */ -#line 343 "parser.y" - { (yyval.var) = BoolVarCreate((yyvsp[(2) - (3)].sval), 0); } +#line 383 "parser.y" + { (yyval.var) = BoolVarCreate((yyvsp[(2) - (3)].sval), false); } break; case 49: /* Line 1806 of yacc.c */ -#line 347 "parser.y" +#line 387 "parser.y" { (yyval.keyCode) = KeycodeCreate((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].num)); } break; case 50: /* Line 1806 of yacc.c */ -#line 351 "parser.y" +#line 391 "parser.y" { (yyval.keyAlias) = KeyAliasCreate((yyvsp[(2) - (5)].sval), (yyvsp[(4) - (5)].sval)); } break; case 51: /* Line 1806 of yacc.c */ -#line 355 "parser.y" +#line 395 "parser.y" { (yyval.vmod) = (yyvsp[(2) - (3)].vmod); } break; case 52: /* Line 1806 of yacc.c */ -#line 359 "parser.y" +#line 399 "parser.y" { (yyval.vmod) = (VModDef *)AppendStmt(&(yyvsp[(1) - (3)].vmod)->common, &(yyvsp[(3) - (3)].vmod)->common); } break; case 53: /* Line 1806 of yacc.c */ -#line 361 "parser.y" +#line 401 "parser.y" { (yyval.vmod) = (yyvsp[(1) - (1)].vmod); } break; case 54: /* Line 1806 of yacc.c */ -#line 365 "parser.y" +#line 405 "parser.y" { (yyval.vmod) = VModCreate((yyvsp[(1) - (1)].sval), NULL); } break; case 55: /* Line 1806 of yacc.c */ -#line 367 "parser.y" +#line 407 "parser.y" { (yyval.vmod) = VModCreate((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].expr)); } break; case 56: /* Line 1806 of yacc.c */ -#line 373 "parser.y" +#line 413 "parser.y" { (yyvsp[(2) - (6)].interp)->def = (yyvsp[(4) - (6)].var); (yyval.interp) = (yyvsp[(2) - (6)].interp); } break; case 57: /* Line 1806 of yacc.c */ -#line 377 "parser.y" - { (yyval.interp) = InterpCreate((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].expr)); } +#line 417 "parser.y" + { (yyval.interp) = InterpCreate((yyvsp[(1) - (3)].keysym), (yyvsp[(3) - (3)].expr)); } break; case 58: /* Line 1806 of yacc.c */ -#line 379 "parser.y" - { (yyval.interp) = InterpCreate((yyvsp[(1) - (1)].str), NULL); } +#line 419 "parser.y" + { (yyval.interp) = InterpCreate((yyvsp[(1) - (1)].keysym), NULL); } break; case 59: /* Line 1806 of yacc.c */ -#line 383 "parser.y" +#line 423 "parser.y" { (yyval.var) = (VarDef *)AppendStmt(&(yyvsp[(1) - (2)].var)->common, &(yyvsp[(2) - (2)].var)->common); } break; case 60: /* Line 1806 of yacc.c */ -#line 385 "parser.y" +#line 425 "parser.y" { (yyval.var) = (yyvsp[(1) - (1)].var); } break; case 61: /* Line 1806 of yacc.c */ -#line 391 "parser.y" +#line 431 "parser.y" { (yyval.keyType) = KeyTypeCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].var)); } break; case 62: /* Line 1806 of yacc.c */ -#line 397 "parser.y" - { (yyval.syms) = SymbolsCreate((yyvsp[(2) - (6)].sval), (ExprDef *)(yyvsp[(4) - (6)].var)); } +#line 437 "parser.y" + { (yyval.syms) = SymbolsCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].var)); } break; case 63: /* Line 1806 of yacc.c */ -#line 401 "parser.y" +#line 441 "parser.y" { (yyval.var) = (VarDef *)AppendStmt(&(yyvsp[(1) - (3)].var)->common, &(yyvsp[(3) - (3)].var)->common); } break; case 64: /* Line 1806 of yacc.c */ -#line 403 "parser.y" +#line 443 "parser.y" { (yyval.var) = (yyvsp[(1) - (1)].var); } break; case 65: /* Line 1806 of yacc.c */ -#line 404 "parser.y" +#line 444 "parser.y" { (yyval.var) = NULL; } break; case 66: /* Line 1806 of yacc.c */ -#line 407 "parser.y" +#line 447 "parser.y" { (yyval.var) = VarCreate((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 67: /* Line 1806 of yacc.c */ -#line 408 "parser.y" +#line 448 "parser.y" { (yyval.var) = VarCreate((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 68: /* Line 1806 of yacc.c */ -#line 409 "parser.y" - { (yyval.var) = BoolVarCreate((yyvsp[(1) - (1)].sval), 1); } +#line 449 "parser.y" + { (yyval.var) = BoolVarCreate((yyvsp[(1) - (1)].sval), true); } break; case 69: /* Line 1806 of yacc.c */ -#line 410 "parser.y" - { (yyval.var) = BoolVarCreate((yyvsp[(2) - (2)].sval), 0); } +#line 450 "parser.y" + { (yyval.var) = BoolVarCreate((yyvsp[(2) - (2)].sval), false); } break; case 70: /* Line 1806 of yacc.c */ -#line 411 "parser.y" +#line 451 "parser.y" { (yyval.var) = VarCreate(NULL, (yyvsp[(1) - (1)].expr)); } break; case 71: /* Line 1806 of yacc.c */ -#line 415 "parser.y" +#line 455 "parser.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 72: /* Line 1806 of yacc.c */ -#line 417 "parser.y" +#line 457 "parser.y" { (yyval.expr) = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, (yyvsp[(2) - (3)].expr)); } break; case 73: /* Line 1806 of yacc.c */ -#line 421 "parser.y" +#line 461 "parser.y" { (yyval.groupCompat) = GroupCompatCreate((yyvsp[(2) - (5)].ival), (yyvsp[(4) - (5)].expr)); } break; case 74: /* Line 1806 of yacc.c */ -#line 425 "parser.y" +#line 465 "parser.y" { (yyval.modMask) = ModMapCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].expr)); } break; case 75: /* Line 1806 of yacc.c */ -#line 429 "parser.y" +#line 469 "parser.y" { (yyval.ledMap) = LedMapCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].var)); } break; case 76: /* Line 1806 of yacc.c */ -#line 433 "parser.y" +#line 473 "parser.y" { (yyval.ledName) = LedNameCreate((yyvsp[(2) - (5)].ival), (yyvsp[(4) - (5)].expr), false); } break; case 77: /* Line 1806 of yacc.c */ -#line 435 "parser.y" +#line 475 "parser.y" { (yyval.ledName) = LedNameCreate((yyvsp[(3) - (6)].ival), (yyvsp[(5) - (6)].expr), true); } break; case 78: /* Line 1806 of yacc.c */ -#line 439 "parser.y" +#line 479 "parser.y" { (yyval.geom) = NULL; } break; case 79: /* Line 1806 of yacc.c */ -#line 441 "parser.y" +#line 481 "parser.y" { (yyval.geom) = NULL; } break; case 80: /* Line 1806 of yacc.c */ -#line 445 "parser.y" +#line 485 "parser.y" { (yyval.geom) = NULL; } break; case 81: /* Line 1806 of yacc.c */ -#line 448 "parser.y" +#line 488 "parser.y" { (yyval.geom) = NULL;} break; case 82: /* Line 1806 of yacc.c */ -#line 449 "parser.y" +#line 489 "parser.y" { (yyval.geom) = NULL; } break; case 83: /* Line 1806 of yacc.c */ -#line 453 "parser.y" +#line 493 "parser.y" { (yyval.geom) = NULL; } break; case 84: /* Line 1806 of yacc.c */ -#line 455 "parser.y" +#line 495 "parser.y" { FreeStmt(&(yyvsp[(1) - (1)].var)->common); (yyval.geom) = NULL; } break; case 85: /* Line 1806 of yacc.c */ -#line 457 "parser.y" +#line 497 "parser.y" { (yyval.geom) = NULL; } break; case 86: /* Line 1806 of yacc.c */ -#line 459 "parser.y" +#line 499 "parser.y" { FreeStmt(&(yyvsp[(1) - (1)].ledMap)->common); (yyval.geom) = NULL; } break; case 87: /* Line 1806 of yacc.c */ -#line 461 "parser.y" +#line 501 "parser.y" { (yyval.geom) = NULL; } break; case 88: /* Line 1806 of yacc.c */ -#line 464 "parser.y" +#line 504 "parser.y" { (yyval.geom) = NULL;} break; case 89: /* Line 1806 of yacc.c */ -#line 465 "parser.y" +#line 505 "parser.y" { (yyval.geom) = NULL; } break; case 90: /* Line 1806 of yacc.c */ -#line 468 "parser.y" +#line 508 "parser.y" { (yyval.geom) = NULL; } break; case 91: /* Line 1806 of yacc.c */ -#line 470 "parser.y" +#line 510 "parser.y" { FreeStmt(&(yyvsp[(1) - (1)].var)->common); (yyval.geom) = NULL; } break; case 92: /* Line 1806 of yacc.c */ -#line 473 "parser.y" +#line 513 "parser.y" { (yyval.geom) = NULL; } break; case 93: /* Line 1806 of yacc.c */ -#line 474 "parser.y" +#line 514 "parser.y" { (yyval.geom) = NULL; } break; case 94: /* Line 1806 of yacc.c */ -#line 478 "parser.y" +#line 518 "parser.y" { (yyval.geom) = NULL; } break; case 95: /* Line 1806 of yacc.c */ -#line 480 "parser.y" +#line 520 "parser.y" { FreeStmt(&(yyvsp[(2) - (3)].expr)->common); (yyval.geom) = NULL; } break; case 96: /* Line 1806 of yacc.c */ -#line 484 "parser.y" +#line 524 "parser.y" { (yyval.geom) = NULL; } break; case 97: /* Line 1806 of yacc.c */ -#line 487 "parser.y" +#line 527 "parser.y" { (yyval.geom) = NULL; } break; case 98: /* Line 1806 of yacc.c */ -#line 488 "parser.y" +#line 528 "parser.y" { (yyval.geom) = NULL; } break; case 99: /* Line 1806 of yacc.c */ -#line 491 "parser.y" +#line 531 "parser.y" { (yyval.geom) = NULL; } break; case 100: /* Line 1806 of yacc.c */ -#line 495 "parser.y" +#line 535 "parser.y" { (yyval.geom) = NULL;} break; case 101: /* Line 1806 of yacc.c */ -#line 497 "parser.y" +#line 537 "parser.y" { (yyval.geom) = NULL; } break; case 102: /* Line 1806 of yacc.c */ -#line 501 "parser.y" +#line 541 "parser.y" { (yyval.geom) = NULL; } break; case 103: /* Line 1806 of yacc.c */ -#line 503 "parser.y" +#line 543 "parser.y" { (yyval.geom) = NULL; } break; case 104: /* Line 1806 of yacc.c */ -#line 505 "parser.y" +#line 545 "parser.y" { FreeStmt(&(yyvsp[(3) - (3)].expr)->common); (yyval.geom) = NULL; } break; case 105: /* Line 1806 of yacc.c */ -#line 509 "parser.y" +#line 549 "parser.y" { (yyval.expr) = NULL; } break; case 106: /* Line 1806 of yacc.c */ -#line 511 "parser.y" +#line 551 "parser.y" { (yyval.expr) = NULL; } break; case 107: /* Line 1806 of yacc.c */ -#line 515 "parser.y" +#line 555 "parser.y" { (yyval.expr) = NULL; } break; case 108: /* Line 1806 of yacc.c */ -#line 519 "parser.y" +#line 559 "parser.y" { FreeStmt(&(yyvsp[(4) - (6)].var)->common); (yyval.geom) = NULL; } break; case 109: /* Line 1806 of yacc.c */ -#line 522 "parser.y" - { (yyval.uval) = 0; } +#line 562 "parser.y" + { (yyval.ival) = 0; } break; case 110: /* Line 1806 of yacc.c */ -#line 523 "parser.y" - { (yyval.uval) = 0; } +#line 563 "parser.y" + { (yyval.ival) = 0; } break; case 111: /* Line 1806 of yacc.c */ -#line 524 "parser.y" - { (yyval.uval) = 0; } +#line 564 "parser.y" + { (yyval.ival) = 0; } break; case 112: /* Line 1806 of yacc.c */ -#line 525 "parser.y" - { (yyval.uval) = 0; } +#line 565 "parser.y" + { (yyval.ival) = 0; } break; case 113: /* Line 1806 of yacc.c */ -#line 528 "parser.y" +#line 568 "parser.y" { (yyval.sval) = (yyvsp[(1) - (1)].sval); } break; case 114: /* Line 1806 of yacc.c */ -#line 529 "parser.y" +#line 569 "parser.y" { (yyval.sval) = (yyvsp[(1) - (1)].sval); } break; case 115: /* Line 1806 of yacc.c */ -#line 533 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "action"); } +#line 573 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "action"); } break; case 116: /* Line 1806 of yacc.c */ -#line 535 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "interpret"); } +#line 575 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "interpret"); } break; case 117: /* Line 1806 of yacc.c */ -#line 537 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "type"); } +#line 577 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "type"); } break; case 118: /* Line 1806 of yacc.c */ -#line 539 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "key"); } +#line 579 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "key"); } break; case 119: /* Line 1806 of yacc.c */ -#line 541 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "group"); } +#line 581 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "group"); } break; case 120: /* Line 1806 of yacc.c */ -#line 543 "parser.y" - {(yyval.sval) = xkb_atom_intern(param->ctx, "modifier_map");} +#line 583 "parser.y" + {(yyval.sval) = xkb_atom_intern_literal(param->ctx, "modifier_map");} break; case 121: /* Line 1806 of yacc.c */ -#line 545 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "indicator"); } +#line 585 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "indicator"); } break; case 122: /* Line 1806 of yacc.c */ -#line 547 "parser.y" +#line 587 "parser.y" { (yyval.sval) = XKB_ATOM_NONE; } break; case 123: /* Line 1806 of yacc.c */ -#line 549 "parser.y" +#line 589 "parser.y" { (yyval.sval) = XKB_ATOM_NONE; } break; case 124: /* Line 1806 of yacc.c */ -#line 551 "parser.y" +#line 591 "parser.y" { (yyval.sval) = XKB_ATOM_NONE; } break; case 125: /* Line 1806 of yacc.c */ -#line 553 "parser.y" +#line 593 "parser.y" { (yyval.sval) = XKB_ATOM_NONE; } break; case 126: /* Line 1806 of yacc.c */ -#line 556 "parser.y" +#line 596 "parser.y" { (yyval.merge) = (yyvsp[(1) - (1)].merge); } break; case 127: /* Line 1806 of yacc.c */ -#line 557 "parser.y" +#line 597 "parser.y" { (yyval.merge) = MERGE_DEFAULT; } break; case 128: /* Line 1806 of yacc.c */ -#line 560 "parser.y" +#line 600 "parser.y" { (yyval.merge) = MERGE_DEFAULT; } break; case 129: /* Line 1806 of yacc.c */ -#line 561 "parser.y" +#line 601 "parser.y" { (yyval.merge) = MERGE_AUGMENT; } break; case 130: /* Line 1806 of yacc.c */ -#line 562 "parser.y" +#line 602 "parser.y" { (yyval.merge) = MERGE_OVERRIDE; } break; case 131: /* Line 1806 of yacc.c */ -#line 563 "parser.y" +#line 603 "parser.y" { (yyval.merge) = MERGE_REPLACE; } break; case 132: /* Line 1806 of yacc.c */ -#line 565 "parser.y" +#line 605 "parser.y" { /* * This used to be MERGE_ALT_FORM. This functionality was @@ -2966,324 +2943,286 @@ yyreduce: case 133: /* Line 1806 of yacc.c */ -#line 574 "parser.y" +#line 614 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 134: /* Line 1806 of yacc.c */ -#line 575 "parser.y" +#line 615 "parser.y" { (yyval.expr) = NULL; } break; case 135: /* Line 1806 of yacc.c */ -#line 579 "parser.y" +#line 619 "parser.y" { (yyval.expr) = (ExprDef *)AppendStmt(&(yyvsp[(1) - (3)].expr)->common, &(yyvsp[(3) - (3)].expr)->common); } break; case 136: /* Line 1806 of yacc.c */ -#line 581 "parser.y" +#line 621 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 137: /* Line 1806 of yacc.c */ -#line 585 "parser.y" +#line 625 "parser.y" { (yyval.expr) = ExprCreateBinary(EXPR_DIVIDE, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 138: /* Line 1806 of yacc.c */ -#line 587 "parser.y" +#line 627 "parser.y" { (yyval.expr) = ExprCreateBinary(EXPR_ADD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 139: /* Line 1806 of yacc.c */ -#line 589 "parser.y" +#line 629 "parser.y" { (yyval.expr) = ExprCreateBinary(EXPR_SUBTRACT, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 140: /* Line 1806 of yacc.c */ -#line 591 "parser.y" +#line 631 "parser.y" { (yyval.expr) = ExprCreateBinary(EXPR_MULTIPLY, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 141: /* Line 1806 of yacc.c */ -#line 593 "parser.y" +#line 633 "parser.y" { (yyval.expr) = ExprCreateBinary(EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 142: /* Line 1806 of yacc.c */ -#line 595 "parser.y" +#line 635 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 143: /* Line 1806 of yacc.c */ -#line 599 "parser.y" - { (yyval.expr) = ExprCreateUnary(EXPR_NEGATE, (yyvsp[(2) - (2)].expr)->value_type, (yyvsp[(2) - (2)].expr)); } +#line 639 "parser.y" + { (yyval.expr) = ExprCreateUnary(EXPR_NEGATE, (yyvsp[(2) - (2)].expr)->expr.value_type, (yyvsp[(2) - (2)].expr)); } break; case 144: /* Line 1806 of yacc.c */ -#line 601 "parser.y" - { (yyval.expr) = ExprCreateUnary(EXPR_UNARY_PLUS, (yyvsp[(2) - (2)].expr)->value_type, (yyvsp[(2) - (2)].expr)); } +#line 641 "parser.y" + { (yyval.expr) = ExprCreateUnary(EXPR_UNARY_PLUS, (yyvsp[(2) - (2)].expr)->expr.value_type, (yyvsp[(2) - (2)].expr)); } break; case 145: /* Line 1806 of yacc.c */ -#line 603 "parser.y" +#line 643 "parser.y" { (yyval.expr) = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, (yyvsp[(2) - (2)].expr)); } break; case 146: /* Line 1806 of yacc.c */ -#line 605 "parser.y" - { (yyval.expr) = ExprCreateUnary(EXPR_INVERT, (yyvsp[(2) - (2)].expr)->value_type, (yyvsp[(2) - (2)].expr)); } +#line 645 "parser.y" + { (yyval.expr) = ExprCreateUnary(EXPR_INVERT, (yyvsp[(2) - (2)].expr)->expr.value_type, (yyvsp[(2) - (2)].expr)); } break; case 147: /* Line 1806 of yacc.c */ -#line 607 "parser.y" +#line 647 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 148: /* Line 1806 of yacc.c */ -#line 609 "parser.y" - { (yyval.expr) = ActionCreate((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); } +#line 649 "parser.y" + { (yyval.expr) = ExprCreateAction((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); } break; case 149: /* Line 1806 of yacc.c */ -#line 611 "parser.y" +#line 651 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 150: /* Line 1806 of yacc.c */ -#line 613 "parser.y" +#line 653 "parser.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 151: /* Line 1806 of yacc.c */ -#line 617 "parser.y" +#line 657 "parser.y" { (yyval.expr) = (ExprDef *)AppendStmt(&(yyvsp[(1) - (3)].expr)->common, &(yyvsp[(3) - (3)].expr)->common); } break; case 152: /* Line 1806 of yacc.c */ -#line 619 "parser.y" +#line 659 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 153: /* Line 1806 of yacc.c */ -#line 623 "parser.y" - { (yyval.expr) = ActionCreate((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); } +#line 663 "parser.y" + { (yyval.expr) = ExprCreateAction((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); } break; case 154: /* Line 1806 of yacc.c */ -#line 627 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN); - expr->value.str = (yyvsp[(1) - (1)].sval); - (yyval.expr) = expr; - } +#line 667 "parser.y" + { (yyval.expr) = ExprCreateIdent((yyvsp[(1) - (1)].sval)); } break; case 155: /* Line 1806 of yacc.c */ -#line 634 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN); - expr->value.field.element = (yyvsp[(1) - (3)].sval); - expr->value.field.field = (yyvsp[(3) - (3)].sval); - (yyval.expr) = expr; - } +#line 669 "parser.y" + { (yyval.expr) = ExprCreateFieldRef((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)); } break; case 156: /* Line 1806 of yacc.c */ -#line 642 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN); - expr->value.array.element = XKB_ATOM_NONE; - expr->value.array.field = (yyvsp[(1) - (4)].sval); - expr->value.array.entry = (yyvsp[(3) - (4)].expr); - (yyval.expr) = expr; - } +#line 671 "parser.y" + { (yyval.expr) = ExprCreateArrayRef(XKB_ATOM_NONE, (yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); } break; case 157: /* Line 1806 of yacc.c */ -#line 651 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN); - expr->value.array.element = (yyvsp[(1) - (6)].sval); - expr->value.array.field = (yyvsp[(3) - (6)].sval); - expr->value.array.entry = (yyvsp[(5) - (6)].expr); - (yyval.expr) = expr; - } +#line 673 "parser.y" + { (yyval.expr) = ExprCreateArrayRef((yyvsp[(1) - (6)].sval), (yyvsp[(3) - (6)].sval), (yyvsp[(5) - (6)].expr)); } break; case 158: /* Line 1806 of yacc.c */ -#line 662 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING); - expr->value.str = (yyvsp[(1) - (1)].sval); - (yyval.expr) = expr; - } +#line 677 "parser.y" + { (yyval.expr) = ExprCreateString((yyvsp[(1) - (1)].sval)); } break; case 159: /* Line 1806 of yacc.c */ -#line 669 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT); - expr->value.ival = (yyvsp[(1) - (1)].ival); - (yyval.expr) = expr; - } +#line 679 "parser.y" + { (yyval.expr) = ExprCreateInteger((yyvsp[(1) - (1)].ival)); } break; case 160: /* Line 1806 of yacc.c */ -#line 676 "parser.y" - { - (yyval.expr) = NULL; - } +#line 681 "parser.y" + { (yyval.expr) = NULL; } break; case 161: /* Line 1806 of yacc.c */ -#line 680 "parser.y" - { - ExprDef *expr; - expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME); - expr->value.keyName = (yyvsp[(1) - (1)].sval); - (yyval.expr) = expr; - } +#line 683 "parser.y" + { (yyval.expr) = ExprCreateKeyName((yyvsp[(1) - (1)].sval)); } break; case 162: /* Line 1806 of yacc.c */ -#line 688 "parser.y" +#line 686 "parser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 163: /* Line 1806 of yacc.c */ -#line 689 "parser.y" +#line 687 "parser.y" { (yyval.expr) = NULL; } break; case 164: /* Line 1806 of yacc.c */ -#line 693 "parser.y" - { (yyval.expr) = AppendKeysymList((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].str)); } +#line 691 "parser.y" + { (yyval.expr) = ExprAppendKeysymList((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].keysym)); } break; case 165: /* Line 1806 of yacc.c */ -#line 695 "parser.y" - { (yyval.expr) = AppendMultiKeysymList((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } +#line 693 "parser.y" + { (yyval.expr) = ExprAppendMultiKeysymList((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; case 166: /* Line 1806 of yacc.c */ -#line 697 "parser.y" - { (yyval.expr) = CreateKeysymList((yyvsp[(1) - (1)].str)); } +#line 695 "parser.y" + { (yyval.expr) = ExprCreateKeysymList((yyvsp[(1) - (1)].keysym)); } break; case 167: /* Line 1806 of yacc.c */ -#line 699 "parser.y" - { (yyval.expr) = CreateMultiKeysymList((yyvsp[(1) - (1)].expr)); } +#line 697 "parser.y" + { (yyval.expr) = ExprCreateMultiKeysymList((yyvsp[(1) - (1)].expr)); } break; case 168: /* Line 1806 of yacc.c */ -#line 703 "parser.y" +#line 701 "parser.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 169: /* Line 1806 of yacc.c */ -#line 706 "parser.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); } +#line 705 "parser.y" + { + if (!resolve_keysym((yyvsp[(1) - (1)].str), &(yyval.keysym))) + parser_warn(param, "unrecognized keysym"); + free((yyvsp[(1) - (1)].str)); + } break; case 170: /* Line 1806 of yacc.c */ -#line 707 "parser.y" - { (yyval.str) = strdup("section"); } +#line 710 "parser.y" + { (yyval.keysym) = XKB_KEY_section; } break; case 171: /* Line 1806 of yacc.c */ -#line 709 "parser.y" +#line 712 "parser.y" { - if ((yyvsp[(1) - (1)].ival) < 10) { /* XK_0 .. XK_9 */ - (yyval.str) = malloc(2); - (yyval.str)[0] = (yyvsp[(1) - (1)].ival) + '0'; - (yyval.str)[1] = '\0'; + if ((yyvsp[(1) - (1)].ival) < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */ + (yyval.keysym) = XKB_KEY_0 + (yyvsp[(1) - (1)].ival); } else { - (yyval.str) = malloc(17); - snprintf((yyval.str), 17, "0x%x", (yyvsp[(1) - (1)].ival)); + char buf[17]; + snprintf(buf, sizeof(buf), "0x%x", (yyvsp[(1) - (1)].ival)); + if (!resolve_keysym(buf, &(yyval.keysym))) + parser_warn(param, "unrecognized keysym"); } } break; @@ -3291,98 +3230,98 @@ yyreduce: case 172: /* Line 1806 of yacc.c */ -#line 722 "parser.y" +#line 725 "parser.y" { (yyval.ival) = -(yyvsp[(2) - (2)].ival); } break; case 173: /* Line 1806 of yacc.c */ -#line 723 "parser.y" +#line 726 "parser.y" { (yyval.ival) = (yyvsp[(1) - (1)].ival); } break; case 174: /* Line 1806 of yacc.c */ -#line 726 "parser.y" +#line 729 "parser.y" { (yyval.ival) = (yyvsp[(1) - (1)].num); } break; case 175: /* Line 1806 of yacc.c */ -#line 727 "parser.y" +#line 730 "parser.y" { (yyval.ival) = (yyvsp[(1) - (1)].num); } break; case 176: /* Line 1806 of yacc.c */ -#line 730 "parser.y" +#line 733 "parser.y" { (yyval.ival) = 0; } break; case 177: /* Line 1806 of yacc.c */ -#line 733 "parser.y" +#line 736 "parser.y" { (yyval.ival) = (yyvsp[(1) - (1)].num); } break; case 178: /* Line 1806 of yacc.c */ -#line 736 "parser.y" +#line 739 "parser.y" { (yyval.num) = (yyvsp[(1) - (1)].num); } break; case 179: /* Line 1806 of yacc.c */ -#line 739 "parser.y" +#line 742 "parser.y" { (yyval.sval) = xkb_atom_steal(param->ctx, (yyvsp[(1) - (1)].str)); } break; case 180: /* Line 1806 of yacc.c */ -#line 740 "parser.y" - { (yyval.sval) = xkb_atom_intern(param->ctx, "default"); } +#line 743 "parser.y" + { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "default"); } break; case 181: /* Line 1806 of yacc.c */ -#line 743 "parser.y" +#line 746 "parser.y" { (yyval.sval) = xkb_atom_steal(param->ctx, (yyvsp[(1) - (1)].str)); } break; case 182: /* Line 1806 of yacc.c */ -#line 746 "parser.y" +#line 749 "parser.y" { (yyval.str) = (yyvsp[(1) - (1)].str); } break; case 183: /* Line 1806 of yacc.c */ -#line 747 "parser.y" +#line 750 "parser.y" { (yyval.str) = NULL; } break; case 184: /* Line 1806 of yacc.c */ -#line 750 "parser.y" +#line 753 "parser.y" { (yyval.str) = (yyvsp[(1) - (1)].str); } break; /* Line 1806 of yacc.c */ -#line 3386 "src/xkbcomp/parser.c" +#line 3325 "src/xkbcomp/parser.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -3403,7 +3342,6 @@ yyreduce: YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; - *++yylsp = yyloc; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule @@ -3433,7 +3371,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (&yylloc, param, YY_("syntax error")); + yyerror (param, YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) @@ -3460,7 +3398,7 @@ yyerrlab: yymsgp = yymsg; } } - yyerror (&yylloc, param, yymsgp); + yyerror (param, yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } @@ -3468,7 +3406,7 @@ yyerrlab: #endif } - yyerror_range[1] = yylloc; + if (yyerrstatus == 3) { @@ -3484,7 +3422,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, param); + yytoken, &yylval, param); yychar = YYEMPTY; } } @@ -3505,7 +3443,6 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -3539,9 +3476,9 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - yyerror_range[1] = *yylsp; + yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp, param); + yystos[yystate], yyvsp, param); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -3549,11 +3486,6 @@ yyerrlab1: *++yyvsp = yylval; - yyerror_range[2] = yylloc; - /* Using YYLLOC is tempting, but would change the location of - the lookahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, yyerror_range, 2); - *++yylsp = yyloc; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); @@ -3581,7 +3513,7 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (&yylloc, param, YY_("memory exhausted")); + yyerror (param, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -3593,7 +3525,7 @@ yyreturn: user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, param); + yytoken, &yylval, param); } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ @@ -3602,7 +3534,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, param); + yystos[*yyssp], yyvsp, param); YYPOPSTACK (1); } #ifndef yyoverflow @@ -3620,7 +3552,7 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 753 "parser.y" +#line 756 "parser.y" #undef scanner @@ -3628,12 +3560,12 @@ yyreturn: XkbFile * parse(struct xkb_context *ctx, void *scanner, const char *map) { - struct parser_param param; int ret; XkbFile *first = NULL; - - param.scanner = scanner; - param.ctx = ctx; + struct parser_param param = { + .scanner = scanner, + .ctx = ctx, + }; /* * If we got a specific map, we look for it exclusively and return @@ -3672,3 +3604,5 @@ parse(struct xkb_context *ctx, void *scanner, const char *map) return first; } +#define scanner param->scanner + diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/parser.h b/src/3rdparty/xkbcommon/src/xkbcomp/parser.h index fba3f4ebd0..f85a2bad85 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/parser.h +++ b/src/3rdparty/xkbcommon/src/xkbcomp/parser.h @@ -175,16 +175,16 @@ typedef union YYSTYPE { /* Line 2068 of yacc.c */ -#line 127 "parser.y" +#line 167 "parser.y" int ival; - unsigned uval; int64_t num; enum xkb_file_type file_type; char *str; xkb_atom_t sval; enum merge_mode merge; enum xkb_map_flags mapFlags; + xkb_keysym_t keysym; ParseCommon *any; ExprDef *expr; VarDef *var; @@ -213,18 +213,4 @@ typedef union YYSTYPE -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - - diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/rules.c b/src/3rdparty/xkbcommon/src/xkbcomp/rules.c index 3f717600fd..de82d96119 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/rules.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/rules.c @@ -47,16 +47,10 @@ * DEALINGS IN THE SOFTWARE. */ -#include -#include -#include -#include -#include -#include - #include "xkbcomp-priv.h" #include "rules.h" #include "include.h" +#include "scanner-utils.h" /* * The rules file @@ -138,25 +132,6 @@ /* Scanner / Lexer */ -/* Point to some substring in the file; used to avoid copying. */ -struct sval { - const char *start; - unsigned int len; -}; -typedef darray(struct sval) darray_sval; - -static inline bool -svaleq(struct sval s1, struct sval s2) -{ - return s1.len == s2.len && strncmp(s1.start, s2.start, s1.len) == 0; -} - -static inline bool -svaleq_prefix(struct sval s1, struct sval s2) -{ - return s1.len <= s2.len && strncmp(s1.start, s2.start, s1.len) == 0; -} - /* Values returned with some tokens, like yylval. */ union lvalue { struct sval string; @@ -170,15 +145,6 @@ struct location { int line, column; }; -struct scanner { - const char *s; - size_t pos; - size_t len; - int line, column; - const char *file_name; - struct xkb_context *ctx; -}; - enum rules_token { TOK_END_OF_FILE = 0, TOK_END_OF_LINE, @@ -190,81 +156,20 @@ enum rules_token { TOK_ERROR }; -static void -scanner_init(struct scanner *s, struct xkb_context *ctx, - const char *string, size_t len, const char *file_name) -{ - s->s = string; - s->len = len; - s->pos = 0; - s->line = s->column = 1; - s->file_name = file_name; - s->ctx = ctx; -} - /* C99 is stupid. Just use the 1 variant when there are no args. */ #define scanner_error1(scanner, loc, msg) \ - log_warn(scanner->ctx, "rules/%s:%d:%d: " msg "\n", \ - scanner->file_name, loc->line, loc->column) + log_warn((scanner)->ctx, "rules/%s:%d:%d: %s\n", \ + (scanner)->file_name, (loc)->line, (loc)->column, msg) #define scanner_error(scanner, loc, fmt, ...) \ - log_warn(scanner->ctx, "rules/%s:%d:%d: " fmt "\n", \ - scanner->file_name, loc->line, loc->column, __VA_ARGS__) - -static char -peek(struct scanner *s) -{ - return s->pos < s->len ? s->s[s->pos] : '\0'; -} - -static bool -eof(struct scanner *s) -{ - return peek(s) == '\0'; -} - -static bool -eol(struct scanner *s) -{ - return peek(s) == '\n'; -} + log_warn((scanner)->ctx, "rules/%s:%d:%d: " fmt "\n", \ + (scanner)->file_name, (loc)->line, (loc)->column, __VA_ARGS__) -static char -next(struct scanner *s) +static inline bool +is_ident(char ch) { - if (eof(s)) - return '\0'; - if (eol(s)) { - s->line++; - s->column = 1; - } - else { - s->column++; - } - return s->s[s->pos++]; + return is_graph(ch) && ch != '\\'; } -static bool -chr(struct scanner *s, char ch) -{ - if (peek(s) != ch) - return false; - s->pos++; s->column++; - return true; -} - -static bool -str(struct scanner *s, const char *string, size_t len) -{ - if (s->len - s->pos < len) - return false; - if (strncasecmp(s->s + s->pos, string, len) != 0) - return false; - s->pos += len; s->column += len; - return true; -} - -#define lit(s, literal) str(s, literal, sizeof(literal) - 1) - static enum rules_token lex(struct scanner *s, union lvalue *val, struct location *loc) { @@ -310,7 +215,7 @@ skip_more_whitespace_and_comments: if (chr(s, '$')) { val->string.start = s->s + s->pos; val->string.len = 0; - while (isgraph(peek(s))) { + while (is_ident(peek(s))) { next(s); val->string.len++; } @@ -323,10 +228,10 @@ skip_more_whitespace_and_comments: } /* Identifier. */ - if (isgraph(peek(s))) { + if (is_ident(peek(s))) { val->string.start = s->s + s->pos; val->string.len = 0; - while (isgraph(peek(s))) { + while (is_ident(peek(s))) { next(s); val->string.len++; } @@ -440,8 +345,8 @@ struct matcher { static struct sval strip_spaces(struct sval v) { - while (v.len > 0 && isspace(v.start[0])) { v.len--; v.start++; } - while (v.len > 0 && isspace(v.start[v.len - 1])) v.len--; + while (v.len > 0 && is_space(v.start[0])) { v.len--; v.start++; } + while (v.len > 0 && is_space(v.start[v.len - 1])) v.len--; return v; } @@ -449,7 +354,6 @@ static darray_sval split_comma_separated_string(const char *s) { darray_sval arr = darray_new(); - struct sval val = { NULL, 0 }; /* * Make sure the array returned by this function always includes at @@ -457,12 +361,13 @@ split_comma_separated_string(const char *s) */ if (!s) { + struct sval val = { NULL, 0 }; darray_append(arr, val); return arr; } while (true) { - val.start = s; val.len = 0; + struct sval val = { s, 0 }; while (*s != '\0' && *s != ',') { s++; val.len++; } darray_append(arr, strip_spaces(val)); if (*s == '\0') break; @@ -482,7 +387,7 @@ matcher_new(struct xkb_context *ctx, m->ctx = ctx; m->rmlvo.model.start = rmlvo->model; - m->rmlvo.model.len = rmlvo->model ? strlen(rmlvo->model) : 0; + m->rmlvo.model.len = strlen_safe(rmlvo->model); m->rmlvo.layouts = split_comma_separated_string(rmlvo->layout); m->rmlvo.variants = split_comma_separated_string(rmlvo->variant); m->rmlvo.options = split_comma_separated_string(rmlvo->options); @@ -505,15 +410,10 @@ matcher_free(struct matcher *m) free(m); } -/* C99 is stupid. Just use the 1 variant when there are no args. */ #define matcher_error1(matcher, msg) \ - log_warn(matcher->ctx, "rules/%s:%d:%d: " msg "\n", \ - matcher->scanner.file_name, matcher->loc.line, \ - matcher->loc.column) + scanner_error1(&(matcher)->scanner, &(matcher)->loc, msg) #define matcher_error(matcher, fmt, ...) \ - log_warn(matcher->ctx, "rules/%s:%d:%d: " fmt "\n", \ - matcher->scanner.file_name, matcher->loc.line, \ - matcher->loc.column, __VA_ARGS__) + scanner_error(&(matcher)->scanner, &(matcher)->loc, fmt, __VA_ARGS__) static void matcher_group_start_new(struct matcher *m, struct sval name) @@ -532,10 +432,9 @@ matcher_group_add_element(struct matcher *m, struct sval element) static void matcher_mapping_start_new(struct matcher *m) { - unsigned int i; - for (i = 0; i < _MLVO_NUM_ENTRIES; i++) + for (unsigned i = 0; i < _MLVO_NUM_ENTRIES; i++) m->mapping.mlvo_at_pos[i] = -1; - for (i = 0; i < _KCCGST_NUM_ENTRIES; i++) + for (unsigned i = 0; i < _KCCGST_NUM_ENTRIES; i++) m->mapping.kccgst_at_pos[i] = -1; m->mapping.layout_idx = m->mapping.variant_idx = XKB_LAYOUT_INVALID; m->mapping.num_mlvo = m->mapping.num_kccgst = 0; @@ -551,7 +450,7 @@ extract_layout_index(const char *s, size_t max_len, xkb_layout_index_t *out) *out = XKB_LAYOUT_INVALID; if (max_len < 3) return -1; - if (s[0] != '[' || !isdigit(s[1]) || s[2] != ']') + if (s[0] != '[' || !is_digit(s[1]) || s[2] != ']') return -1; if (s[1] - '0' < 1 || s[1] - '0' > XKB_MAX_GROUPS) return -1; @@ -565,8 +464,6 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident) { enum rules_mlvo mlvo; struct sval mlvo_sval; - xkb_layout_index_t idx; - int consumed; for (mlvo = 0; mlvo < _MLVO_NUM_ENTRIES; mlvo++) { mlvo_sval = rules_mlvo_svals[mlvo]; @@ -596,8 +493,9 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident) /* If there are leftovers still, it must be an index. */ if (mlvo_sval.len < ident.len) { - consumed = extract_layout_index(ident.start + mlvo_sval.len, - ident.len - mlvo_sval.len, &idx); + xkb_layout_index_t idx; + int consumed = extract_layout_index(ident.start + mlvo_sval.len, + ident.len - mlvo_sval.len, &idx); if ((int) (ident.len - mlvo_sval.len) != consumed) { matcher_error(m, "invalid mapping:\" %.*s\" may only be followed by a valid group index; " @@ -822,14 +720,8 @@ static bool append_expanded_kccgst_value(struct matcher *m, darray_char *to, struct sval value) { - unsigned int i; - size_t original_size = darray_size(*to); + const size_t original_size = darray_size(*to); const char *s = value.start; - xkb_layout_index_t idx; - int consumed; - enum rules_mlvo mlv; - struct sval expanded; - char pfx, sfx; /* * Appending bar to foo -> foo (not an error if this happens) @@ -847,7 +739,12 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to, * Some ugly hand-lexing here, but going through the scanner is more * trouble than it's worth, and the format is ugly on its own merit. */ - for (i = 0; i < value.len; ) { + for (unsigned i = 0; i < value.len; ) { + enum rules_mlvo mlv; + xkb_layout_index_t idx; + char pfx, sfx; + struct sval expanded; + /* Check if that's a start of an expansion. */ if (s[i] != '%') { /* Just a normal character. */ @@ -876,22 +773,19 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to, /* Check for index. */ idx = XKB_LAYOUT_INVALID; - if (i < value.len) { - if (s[i] == '[') { - if (mlv != MLVO_LAYOUT && mlv != MLVO_VARIANT) { - matcher_error1(m, - "invalid index in %%-expansion; " - "may only index layout or variant"); - goto error; - } - - consumed = extract_layout_index(s + i, value.len - i, &idx); - if (consumed == -1) goto error; - i += consumed; - } - else { - idx = XKB_LAYOUT_INVALID; + if (i < value.len && s[i] == '[') { + int consumed; + + if (mlv != MLVO_LAYOUT && mlv != MLVO_VARIANT) { + matcher_error1(m, + "invalid index in %%-expansion; " + "may only index layout or variant"); + goto error; } + + consumed = extract_layout_index(s + i, value.len - i, &idx); + if (consumed == -1) goto error; + i += consumed; } /* Check for suffix, if there supposed to be one. */ @@ -959,37 +853,31 @@ matcher_rule_verify(struct matcher *m) static void matcher_rule_apply_if_matches(struct matcher *m) { - unsigned int i; - enum rules_mlvo mlvo; - enum rules_kccgst kccgst; - struct sval value, *option; - enum mlvo_match_type match_type; - bool matched = false; - xkb_layout_index_t idx; - - for (i = 0; i < m->mapping.num_mlvo; i++) { - mlvo = m->mapping.mlvo_at_pos[i]; - value = m->rule.mlvo_value_at_pos[i]; - match_type = m->rule.match_type_at_pos[i]; + for (unsigned i = 0; i < m->mapping.num_mlvo; i++) { + enum rules_mlvo mlvo = m->mapping.mlvo_at_pos[i]; + struct sval value = m->rule.mlvo_value_at_pos[i]; + enum mlvo_match_type match_type = m->rule.match_type_at_pos[i]; + bool matched = false; if (mlvo == MLVO_MODEL) { matched = match_value(m, value, m->rmlvo.model, match_type); } else if (mlvo == MLVO_LAYOUT) { - idx = m->mapping.layout_idx; + xkb_layout_index_t idx = m->mapping.layout_idx; idx = (idx == XKB_LAYOUT_INVALID ? 0 : idx); matched = match_value(m, value, darray_item(m->rmlvo.layouts, idx), match_type); } else if (mlvo == MLVO_VARIANT) { - idx = m->mapping.layout_idx; + xkb_layout_index_t idx = m->mapping.layout_idx; idx = (idx == XKB_LAYOUT_INVALID ? 0 : idx); matched = match_value(m, value, darray_item(m->rmlvo.variants, idx), match_type); } else if (mlvo == MLVO_OPTION) { + struct sval *option; darray_foreach(option, m->rmlvo.options) { matched = match_value(m, value, *option, match_type); if (matched) @@ -1001,9 +889,9 @@ matcher_rule_apply_if_matches(struct matcher *m) return; } - for (i = 0; i < m->mapping.num_kccgst; i++) { - kccgst = m->mapping.kccgst_at_pos[i]; - value = m->rule.kccgst_value_at_pos[i]; + for (unsigned i = 0; i < m->mapping.num_kccgst; i++) { + enum rules_kccgst kccgst = m->mapping.kccgst_at_pos[i]; + struct sval value = m->rule.kccgst_value_at_pos[i]; append_expanded_kccgst_value(m, &m->kccgst[kccgst], value); } @@ -1193,36 +1081,27 @@ xkb_components_from_rules(struct xkb_context *ctx, bool ret = false; FILE *file; char *path; - int fd; - struct stat stat_buf; - char *string; + const char *string; + size_t size; struct matcher *matcher; file = FindFileInXkbPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path); if (!file) goto err_out; - fd = fileno(file); - - if (fstat(fd, &stat_buf) != 0) { - log_err(ctx, "Couldn't stat rules file\n"); - goto err_file; - } - - string = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (string == MAP_FAILED) { - log_err(ctx, "Couldn't mmap rules file (%lld bytes)\n", - (long long) stat_buf.st_size); + ret = map_file(file, &string, &size); + if (!ret) { + log_err(ctx, "Couldn't read rules file: %s\n", strerror(errno)); goto err_file; } matcher = matcher_new(ctx, rmlvo); - ret = matcher_match(matcher, string, stat_buf.st_size, rmlvo->rules, out); + ret = matcher_match(matcher, string, size, rmlvo->rules, out); if (!ret) log_err(ctx, "No components returned from XKB rules \"%s\"\n", path); matcher_free(matcher); - munmap(string, stat_buf.st_size); + unmap_file(string, size); err_file: free(path); fclose(file); diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/scanner-utils.h b/src/3rdparty/xkbcommon/src/xkbcomp/scanner-utils.h new file mode 100644 index 0000000000..7e21b00662 --- /dev/null +++ b/src/3rdparty/xkbcommon/src/xkbcomp/scanner-utils.h @@ -0,0 +1,145 @@ +/* + * Copyright © 2012 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef XKBCOMP_SCANNER_UTILS_H +#define XKBCOMP_SCANNER_UTILS_H + +/* Point to some substring in the file; used to avoid copying. */ +struct sval { + const char *start; + unsigned int len; +}; +typedef darray(struct sval) darray_sval; + +static inline bool +svaleq(struct sval s1, struct sval s2) +{ + return s1.len == s2.len && strncmp(s1.start, s2.start, s1.len) == 0; +} + +static inline bool +svaleq_prefix(struct sval s1, struct sval s2) +{ + return s1.len <= s2.len && strncmp(s1.start, s2.start, s1.len) == 0; +} + +struct scanner { + const char *s; + size_t pos; + size_t len; + char buf[1024]; + size_t buf_pos; + int line, column; + /* The line/column of the start of the current token. */ + int token_line, token_column; + const char *file_name; + struct xkb_context *ctx; +}; + +static inline void +scanner_init(struct scanner *s, struct xkb_context *ctx, + const char *string, size_t len, const char *file_name) +{ + s->s = string; + s->len = len; + s->pos = 0; + s->line = s->column = 1; + s->token_line = s->token_column = 1; + s->file_name = file_name; + s->ctx = ctx; +} + +static inline char +peek(struct scanner *s) +{ + return s->pos < s->len ? s->s[s->pos] : '\0'; +} + +static inline bool +eof(struct scanner *s) +{ + return s->pos >= s->len; +} + +static inline bool +eol(struct scanner *s) +{ + return peek(s) == '\n'; +} + +static inline char +next(struct scanner *s) +{ + if (eof(s)) + return '\0'; + if (eol(s)) { + s->line++; + s->column = 1; + } + else { + s->column++; + } + return s->s[s->pos++]; +} + +static inline bool +chr(struct scanner *s, char ch) +{ + if (peek(s) != ch) + return false; + s->pos++; s->column++; + return true; +} + +static inline bool +str(struct scanner *s, const char *string, size_t len) +{ + if (s->len - s->pos < len) + return false; + if (strncasecmp(s->s + s->pos, string, len) != 0) + return false; + s->pos += len; s->column += len; + return true; +} + +#define lit(s, literal) str(s, literal, sizeof(literal) - 1) + +static inline bool +buf_append(struct scanner *s, char ch) +{ + if (s->buf_pos + 1 >= sizeof(s->buf)) + return false; + s->buf[s->buf_pos++] = ch; + return true; +} + +static inline bool +oct(struct scanner *s, uint8_t *out) +{ + int i; + for (i = 0, *out = 0; peek(s) >= '0' && peek(s) <= '7' && i < 3; i++) + *out = *out * 8 + next(s) - '0'; + return i > 0; +} + +#endif diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c b/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c index 4731107b85..48df488547 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c @@ -1,2861 +1,219 @@ -#line 2 "src/xkbcomp/scanner.c" - -#line 4 "src/xkbcomp/scanner.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* An opaque pointer. */ -#ifndef YY_TYPEDEF_YY_SCANNER_T -#define YY_TYPEDEF_YY_SCANNER_T -typedef void* yyscan_t; -#endif - -/* For convenience, these vars (plus the bison vars far below) - are macros in the reentrant scanner. */ -#define yyin yyg->yyin_r -#define yyout yyg->yyout_r -#define yyextra yyg->yyextra_r -#define yyleng yyg->yyleng_r -#define yytext yyg->yytext_r -#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) -#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) -#define yy_flex_debug yyg->yy_flex_debug_r - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yyg->yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yyg->yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE _xkbcommon_restart(yyin ,yyscanner ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires - * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE _xkbcommon_lex. - * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-yylineno scanner, because yy_act is - * normally declared as a register variable-- so it is not worth it. - */ - #define YY_LESS_LINENO(n) \ - do { \ - int yyl;\ - for ( yyl = n; yyl < yyleng; ++yyl )\ - if ( yytext[yyl] == '\n' )\ - --yylineno;\ - }while(0) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = yyg->yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via _xkbcommon_restart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ - ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] - -void _xkbcommon_restart (FILE *input_file ,yyscan_t yyscanner ); -void _xkbcommon__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE _xkbcommon__create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void _xkbcommon__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void _xkbcommon__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void _xkbcommon_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void _xkbcommon_pop_buffer_state (yyscan_t yyscanner ); - -static void _xkbcommon_ensure_buffer_stack (yyscan_t yyscanner ); -static void _xkbcommon__load_buffer_state (yyscan_t yyscanner ); -static void _xkbcommon__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); - -#define YY_FLUSH_BUFFER _xkbcommon__flush_buffer(YY_CURRENT_BUFFER ,yyscanner) - -YY_BUFFER_STATE _xkbcommon__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE _xkbcommon__scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE _xkbcommon__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); - -void *_xkbcommon_alloc (yy_size_t ,yyscan_t yyscanner ); -void *_xkbcommon_realloc (void *,yy_size_t ,yyscan_t yyscanner ); -void _xkbcommon_free (void * ,yyscan_t yyscanner ); - -#define yy_new_buffer _xkbcommon__create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - _xkbcommon_ensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - _xkbcommon__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - _xkbcommon_ensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - _xkbcommon__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -#define _xkbcommon_wrap(n) 1 -#define YY_SKIP_YYWRAP - -typedef unsigned char YY_CHAR; - -typedef int yy_state_type; - -#define yytext_ptr yytext_r - -static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); -static int yy_get_next_buffer (yyscan_t yyscanner ); -static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yyg->yytext_ptr = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ - yyg->yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yyg->yy_c_buf_p = yy_cp; - -#define YY_NUM_RULES 83 -#define YY_END_OF_BUFFER 84 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[336] = - { 0, - 0, 0, 0, 0, 84, 82, 81, 81, 79, 3, - 2, 72, 73, 69, 66, 77, 67, 76, 68, 63, - 63, 78, 82, 65, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 74, 75, 70, 71, 80, 14, 83, 4, 14, - 81, 2, 1, 0, 63, 0, 0, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 5, 6, 10, 13, 11, 7, 9, 8, 12, - 1, 64, 62, 15, 61, 61, 61, 61, 61, 61, - - 61, 61, 61, 61, 61, 61, 39, 61, 61, 61, - 61, 61, 61, 47, 61, 61, 61, 61, 61, 61, - 61, 5, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 48, 54, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 51, 36, 61, - 61, 5, 61, 40, 61, 61, 61, 61, 61, 41, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 46, 53, 61, 61, 61, 61, - 61, 61, 61, 38, 61, 61, 61, 61, 61, 34, - 61, 61, 61, 61, 61, 42, 61, 61, 61, 61, - - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 29, 33, 61, 27, 61, 61, 61, - 61, 43, 52, 50, 61, 32, 30, 49, 55, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 28, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 31, 61, 45, 37, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 18, 61, - 61, 61, 61, 61, 61, 61, 20, 61, 61, 16, - 26, 61, 61, 61, 61, 61, 58, 61, 61, 61, - 61, 61, 61, 61, 61, 19, 61, 61, 61, 61, - - 44, 61, 61, 61, 24, 17, 61, 61, 61, 59, - 57, 61, 61, 61, 25, 61, 61, 61, 61, 21, - 61, 60, 61, 61, 61, 61, 61, 56, 35, 22, - 61, 61, 61, 23, 0 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 6, 1, 1, 1, 1, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, - 16, 16, 16, 16, 16, 17, 17, 1, 18, 19, - 20, 21, 1, 1, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 31, 38, 39, 40, 41, 42, 43, 44, 45, 31, - 46, 47, 48, 1, 49, 1, 50, 51, 52, 53, - - 54, 55, 56, 57, 58, 31, 59, 60, 61, 62, - 63, 64, 31, 65, 66, 67, 68, 69, 70, 71, - 72, 31, 73, 1, 74, 75, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst flex_int32_t yy_meta[76] = - { 0, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, - 1, 3, 1, 1, 4, 4, 4, 1, 1, 1, - 1, 4, 4, 4, 4, 4, 4, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 1, 1, 1, 5, 4, - 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 1, 1, 1 - } ; - -static yyconst flex_int16_t yy_base[342] = - { 0, - 0, 0, 73, 74, 263, 695, 78, 80, 695, 695, - 0, 695, 695, 695, 695, 695, 695, 695, 203, 71, - 76, 695, 0, 695, 66, 0, 59, 54, 58, 67, - 65, 75, 67, 68, 64, 86, 83, 109, 98, 81, - 82, 695, 695, 695, 695, 695, 695, 695, 695, 158, - 114, 0, 0, 132, 138, 0, 158, 0, 100, 128, - 100, 123, 109, 124, 136, 166, 131, 141, 152, 140, - 156, 150, 157, 156, 159, 179, 171, 164, 177, 178, - 179, 221, 229, 695, 695, 695, 695, 695, 695, 695, - 0, 232, 0, 695, 192, 202, 199, 206, 200, 217, - - 216, 201, 226, 220, 224, 229, 220, 222, 232, 231, - 227, 230, 238, 0, 232, 236, 244, 236, 251, 247, - 115, 279, 252, 250, 256, 263, 278, 266, 268, 272, - 284, 271, 289, 279, 296, 0, 0, 292, 298, 288, - 293, 292, 296, 305, 301, 307, 312, 0, 0, 288, - 342, 347, 305, 0, 307, 310, 315, 320, 313, 0, - 323, 335, 346, 336, 351, 348, 346, 357, 349, 364, - 357, 367, 366, 356, 0, 0, 371, 359, 371, 373, - 381, 379, 367, 0, 372, 394, 380, 383, 390, 0, - 402, 390, 394, 113, 408, 0, 399, 411, 396, 413, - - 409, 417, 410, 413, 414, 413, 407, 409, 421, 424, - 423, 427, 424, 0, 0, 432, 0, 434, 448, 445, - 440, 0, 0, 0, 454, 0, 0, 0, 110, 446, - 450, 462, 453, 468, 469, 467, 472, 473, 108, 457, - 461, 477, 63, 0, 472, 485, 483, 476, 491, 474, - 482, 483, 485, 487, 61, 497, 0, 0, 485, 500, - 500, 498, 500, 518, 508, 507, 508, 516, 0, 520, - 525, 528, 519, 529, 538, 537, 538, 526, 540, 0, - 0, 539, 534, 546, 539, 534, 0, 535, 547, 556, - 566, 558, 548, 556, 575, 0, 53, 565, 563, 564, - - 0, 578, 578, 587, 0, 0, 573, 581, 574, 0, - 0, 580, 583, 581, 0, 595, 586, 598, 595, 0, - 586, 0, 594, 594, 596, 602, 599, 0, 0, 49, - 612, 604, 610, 0, 695, 674, 679, 682, 684, 689, - 90 - } ; - -static yyconst flex_int16_t yy_def[342] = - { 0, - 335, 1, 336, 336, 335, 335, 335, 335, 335, 335, - 337, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 338, 335, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 337, 340, 335, 335, 341, 338, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 340, 335, 341, 335, 339, 339, 339, 339, 339, 339, - - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 335, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 335, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 0, 335, 335, 335, 335, 335, - 335 - } ; - -static yyconst flex_int16_t yy_nxt[771] = - { 0, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, - 6, 25, 26, 26, 27, 26, 28, 29, 30, 31, - 26, 32, 33, 34, 26, 35, 36, 37, 38, 39, - 26, 40, 26, 41, 26, 42, 6, 43, 26, 25, - 26, 26, 27, 26, 28, 29, 30, 31, 32, 33, - 34, 26, 35, 36, 37, 38, 39, 26, 40, 26, - 41, 26, 44, 45, 46, 48, 48, 49, 49, 51, - 51, 51, 51, 54, 62, 55, 55, 55, 54, 59, - 55, 55, 55, 93, 63, 64, 65, 331, 60, 66, - - 67, 308, 68, 69, 70, 71, 61, 72, 73, 271, - 80, 260, 62, 81, 56, 51, 51, 59, 74, 50, - 50, 63, 64, 78, 65, 60, 66, 99, 67, 68, - 69, 70, 71, 61, 75, 72, 73, 76, 80, 95, - 81, 56, 79, 101, 77, 74, 92, 92, 92, 100, - 54, 78, 55, 55, 55, 99, 256, 96, 245, 102, - 103, 220, 75, 151, 97, 76, 95, 98, 108, 79, - 101, 77, 82, 82, 83, 107, 109, 100, 94, 110, - 84, 111, 115, 85, 86, 96, 102, 112, 103, 104, - 105, 97, 87, 113, 98, 88, 108, 89, 114, 90, - - 116, 121, 107, 117, 109, 106, 110, 118, 84, 111, - 115, 85, 86, 119, 112, 120, 53, 104, 105, 87, - 113, 123, 88, 124, 89, 114, 90, 125, 116, 121, - 117, 126, 106, 127, 118, 122, 122, 83, 128, 129, - 119, 130, 120, 83, 83, 83, 92, 92, 92, 123, - 131, 124, 132, 133, 134, 125, 135, 137, 136, 126, - 127, 138, 335, 141, 142, 139, 128, 129, 130, 143, - 144, 145, 146, 147, 335, 148, 149, 155, 131, 132, - 140, 133, 134, 135, 137, 136, 150, 153, 154, 138, - 141, 142, 139, 152, 152, 83, 143, 144, 145, 146, - - 156, 147, 148, 157, 149, 155, 158, 159, 160, 161, - 335, 162, 163, 150, 153, 154, 164, 165, 166, 167, - 335, 168, 169, 335, 170, 172, 173, 156, 177, 171, - 174, 157, 175, 158, 159, 160, 176, 161, 162, 184, - 163, 185, 189, 164, 186, 165, 166, 167, 168, 187, - 169, 170, 188, 172, 173, 177, 171, 190, 174, 191, - 175, 83, 83, 83, 176, 178, 184, 192, 185, 179, - 189, 186, 193, 180, 181, 194, 187, 195, 197, 188, - 182, 183, 196, 198, 190, 199, 200, 191, 201, 202, - 335, 203, 204, 178, 205, 192, 206, 179, 207, 193, - - 180, 181, 208, 194, 209, 195, 197, 182, 183, 196, - 198, 211, 212, 199, 200, 213, 201, 202, 203, 214, - 204, 205, 215, 210, 206, 216, 207, 217, 335, 218, - 208, 219, 209, 221, 335, 222, 223, 225, 211, 212, - 224, 226, 227, 213, 228, 229, 214, 230, 231, 215, - 210, 232, 216, 233, 234, 217, 218, 235, 219, 236, - 237, 221, 222, 238, 223, 225, 239, 224, 226, 240, - 227, 228, 229, 241, 230, 231, 242, 243, 232, 244, - 233, 234, 246, 247, 235, 248, 236, 237, 250, 251, - 238, 252, 253, 239, 257, 249, 240, 254, 255, 335, - - 258, 241, 259, 242, 243, 261, 262, 244, 263, 246, - 247, 264, 265, 248, 266, 250, 267, 251, 268, 252, - 253, 257, 249, 269, 270, 254, 255, 258, 272, 273, - 259, 274, 261, 275, 262, 276, 263, 277, 264, 278, - 265, 266, 279, 267, 280, 268, 281, 282, 283, 284, - 269, 270, 285, 286, 288, 272, 273, 287, 274, 289, - 275, 290, 276, 293, 277, 294, 278, 291, 295, 297, - 279, 280, 296, 281, 282, 283, 298, 284, 299, 300, - 285, 286, 288, 301, 287, 302, 292, 289, 303, 290, - 293, 304, 305, 294, 306, 291, 295, 297, 307, 296, - - 309, 310, 311, 298, 312, 299, 300, 313, 314, 318, - 301, 315, 316, 302, 317, 319, 303, 320, 304, 305, - 321, 306, 322, 323, 324, 333, 307, 309, 310, 311, - 325, 326, 312, 327, 328, 313, 314, 318, 315, 316, - 329, 317, 319, 330, 320, 332, 334, 335, 321, 322, - 335, 323, 324, 333, 335, 335, 335, 325, 326, 335, - 327, 328, 335, 335, 335, 335, 335, 329, 335, 335, - 330, 335, 332, 334, 47, 47, 47, 47, 47, 52, - 335, 52, 52, 52, 57, 57, 57, 58, 58, 91, - 335, 91, 91, 91, 5, 335, 335, 335, 335, 335, - - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335 - } ; - -static yyconst flex_int16_t yy_chk[771] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 4, 3, 4, 7, - 7, 8, 8, 20, 27, 20, 20, 20, 21, 25, - 21, 21, 21, 341, 28, 29, 30, 330, 25, 31, - - 32, 297, 33, 34, 35, 35, 25, 36, 37, 255, - 40, 243, 27, 41, 20, 51, 51, 25, 37, 3, - 4, 28, 29, 39, 30, 25, 31, 61, 32, 33, - 34, 35, 35, 25, 38, 36, 37, 38, 40, 59, - 41, 20, 39, 63, 38, 37, 54, 54, 54, 62, - 55, 39, 55, 55, 55, 61, 239, 60, 229, 64, - 65, 194, 38, 121, 60, 38, 59, 60, 68, 39, - 63, 38, 50, 50, 50, 67, 69, 62, 57, 70, - 50, 71, 75, 50, 50, 60, 64, 72, 65, 66, - 66, 60, 50, 73, 60, 50, 68, 50, 74, 50, - - 76, 81, 67, 77, 69, 66, 70, 78, 50, 71, - 75, 50, 50, 79, 72, 80, 19, 66, 66, 50, - 73, 95, 50, 96, 50, 74, 50, 97, 76, 81, - 77, 98, 66, 99, 78, 82, 82, 82, 100, 101, - 79, 102, 80, 83, 83, 83, 92, 92, 92, 95, - 103, 96, 104, 105, 106, 97, 107, 108, 107, 98, - 99, 109, 5, 110, 111, 109, 100, 101, 102, 112, - 113, 115, 116, 117, 0, 118, 119, 125, 103, 104, - 109, 105, 106, 107, 108, 107, 120, 123, 124, 109, - 110, 111, 109, 122, 122, 122, 112, 113, 115, 116, - - 126, 117, 118, 127, 119, 125, 128, 129, 130, 131, - 0, 132, 133, 120, 123, 124, 134, 135, 138, 139, - 0, 140, 141, 0, 142, 143, 144, 126, 150, 142, - 145, 127, 146, 128, 129, 130, 147, 131, 132, 153, - 133, 155, 159, 134, 156, 135, 138, 139, 140, 157, - 141, 142, 158, 143, 144, 150, 142, 161, 145, 162, - 146, 152, 152, 152, 147, 151, 153, 163, 155, 151, - 159, 156, 164, 151, 151, 165, 157, 166, 168, 158, - 151, 151, 167, 169, 161, 170, 171, 162, 172, 173, - 0, 174, 177, 151, 178, 163, 179, 151, 180, 164, - - 151, 151, 181, 165, 182, 166, 168, 151, 151, 167, - 169, 183, 185, 170, 171, 186, 172, 173, 174, 187, - 177, 178, 188, 182, 179, 189, 180, 191, 0, 192, - 181, 193, 182, 195, 0, 197, 198, 200, 183, 185, - 199, 201, 202, 186, 203, 204, 187, 205, 206, 188, - 182, 207, 189, 208, 209, 191, 192, 210, 193, 211, - 212, 195, 197, 213, 198, 200, 216, 199, 201, 218, - 202, 203, 204, 219, 205, 206, 220, 221, 207, 225, - 208, 209, 230, 231, 210, 232, 211, 212, 233, 234, - 213, 235, 236, 216, 240, 232, 218, 237, 238, 0, - - 241, 219, 242, 220, 221, 245, 246, 225, 247, 230, - 231, 248, 249, 232, 250, 233, 251, 234, 252, 235, - 236, 240, 232, 253, 254, 237, 238, 241, 256, 259, - 242, 260, 245, 260, 246, 261, 247, 262, 248, 263, - 249, 250, 264, 251, 265, 252, 266, 267, 268, 270, - 253, 254, 271, 272, 274, 256, 259, 273, 260, 275, - 260, 276, 261, 278, 262, 279, 263, 277, 282, 284, - 264, 265, 283, 266, 267, 268, 285, 270, 286, 288, - 271, 272, 274, 289, 273, 290, 277, 275, 291, 276, - 278, 292, 293, 279, 294, 277, 282, 284, 295, 283, - - 298, 299, 300, 285, 302, 286, 288, 303, 304, 312, - 289, 307, 308, 290, 309, 313, 291, 314, 292, 293, - 316, 294, 317, 318, 319, 332, 295, 298, 299, 300, - 321, 323, 302, 324, 325, 303, 304, 312, 307, 308, - 326, 309, 313, 327, 314, 331, 333, 0, 316, 317, - 0, 318, 319, 332, 0, 0, 0, 321, 323, 0, - 324, 325, 0, 0, 0, 0, 0, 326, 0, 0, - 327, 0, 331, 333, 336, 336, 336, 336, 336, 337, - 0, 337, 337, 337, 338, 338, 338, 339, 339, 340, - 0, 340, 340, 340, 335, 335, 335, 335, 335, 335, - - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335 - } ; - -/* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[84] = - { 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, }; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -#line 1 "scanner.l" -/************************************************************ - Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. - - Permission to use, copy, modify, and distribute this - software and its documentation for any purpose and without - fee is hereby granted, provided that the above copyright - notice appear in all copies and that both that copyright - notice and this permission notice appear in supporting - documentation, and that the name of Silicon Graphics not be - used in advertising or publicity pertaining to distribution - of the software without specific prior written permission. - Silicon Graphics makes no representation about the suitability - of this software for any purpose. It is provided "as is" - without any express or implied warranty. - - SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON - GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH - THE USE OR PERFORMANCE OF THIS SOFTWARE. - - ********************************************************/ -#line 28 "scanner.l" -#include "xkbcomp-priv.h" -#include "parser-priv.h" - -#pragma GCC diagnostic ignored "-Wmissing-noreturn" -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC diagnostic push - -struct scanner_extra { - struct xkb_context *ctx; - const char *file_name; - char scanBuf[1024]; - char *s; -}; - -static void -scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra, - const char *msg); - -#define YY_USER_ACTION { \ - yylloc->first_line = yylineno; \ - yylloc->last_line = yylineno; \ -} - -#define APPEND_S(ch) do { \ - if (yyextra->s - yyextra->scanBuf >= sizeof(yyextra->scanBuf) - 1) \ - return ERROR_TOK; \ - *yyextra->s++ = ch; \ -} while (0) -#define YY_NO_UNISTD_H 1 -#define YY_NO_INPUT 1 - -#line 803 "src/xkbcomp/scanner.c" - -#define INITIAL 0 -#define S_STR 1 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#define YY_EXTRA_TYPE struct scanner_extra * - -/* Holds the entire state of the reentrant scanner. */ -struct yyguts_t - { - - /* User-defined. Not touched by flex. */ - YY_EXTRA_TYPE yyextra_r; - - /* The rest are the same as the globals declared in the non-reentrant scanner. */ - FILE *yyin_r, *yyout_r; - size_t yy_buffer_stack_top; /**< index of top of stack. */ - size_t yy_buffer_stack_max; /**< capacity of stack. */ - YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ - char yy_hold_char; - int yy_n_chars; - int yyleng_r; - char *yy_c_buf_p; - int yy_init; - int yy_start; - int yy_did_buffer_switch_on_eof; - int yy_start_stack_ptr; - int yy_start_stack_depth; - int *yy_start_stack; - yy_state_type yy_last_accepting_state; - char* yy_last_accepting_cpos; - - int yylineno_r; - int yy_flex_debug_r; - - char *yytext_r; - int yy_more_flag; - int yy_more_len; - - YYSTYPE * yylval_r; - - YYLTYPE * yylloc_r; - - }; /* end struct yyguts_t */ - -static int yy_init_globals (yyscan_t yyscanner ); - - /* This must go here because YYSTYPE and YYLTYPE are included - * from bison output in section 1.*/ - # define yylval yyg->yylval_r - - # define yylloc yyg->yylloc_r - -int _xkbcommon_lex_init (yyscan_t* scanner); - -int _xkbcommon_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int _xkbcommon_lex_destroy (yyscan_t yyscanner ); - -int _xkbcommon_get_debug (yyscan_t yyscanner ); - -void _xkbcommon_set_debug (int debug_flag ,yyscan_t yyscanner ); - -YY_EXTRA_TYPE _xkbcommon_get_extra (yyscan_t yyscanner ); - -void _xkbcommon_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); - -FILE *_xkbcommon_get_in (yyscan_t yyscanner ); - -void _xkbcommon_set_in (FILE * in_str ,yyscan_t yyscanner ); - -FILE *_xkbcommon_get_out (yyscan_t yyscanner ); - -void _xkbcommon_set_out (FILE * out_str ,yyscan_t yyscanner ); - -int _xkbcommon_get_leng (yyscan_t yyscanner ); - -char *_xkbcommon_get_text (yyscan_t yyscanner ); - -int _xkbcommon_get_lineno (yyscan_t yyscanner ); - -void _xkbcommon_set_lineno (int line_number ,yyscan_t yyscanner ); - -YYSTYPE * _xkbcommon_get_lval (yyscan_t yyscanner ); - -void _xkbcommon_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); - - YYLTYPE *_xkbcommon_get_lloc (yyscan_t yyscanner ); - - void _xkbcommon_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int _xkbcommon_wrap (yyscan_t yyscanner ); -#else -extern int _xkbcommon_wrap (yyscan_t yyscanner ); -#endif -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (yyscan_t yyscanner ); -#else -static int input (yyscan_t yyscanner ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int _xkbcommon_lex \ - (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); - -#define YY_DECL int _xkbcommon_lex \ - (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - -#line 69 "scanner.l" - - -#line 1049 "src/xkbcomp/scanner.c" - - yylval = yylval_param; - - yylloc = yylloc_param; - - if ( !yyg->yy_init ) - { - yyg->yy_init = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yyg->yy_start ) - yyg->yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - _xkbcommon_ensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - _xkbcommon__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); - } - - _xkbcommon__load_buffer_state(yyscanner ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = yyg->yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yyg->yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yyg->yy_start; -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 336 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_current_state != 335 ); - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - - YY_DO_BEFORE_ACTION; - - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - int yyl; - for ( yyl = 0; yyl < yyleng; ++yyl ) - if ( yytext[yyl] == '\n' ) - - do{ yylineno++; - yycolumn=0; - }while(0) -; - } - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yyg->yy_hold_char; - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 71 "scanner.l" - - YY_BREAK -case 2: -YY_RULE_SETUP -#line 72 "scanner.l" - - YY_BREAK -case 3: -YY_RULE_SETUP -#line 74 "scanner.l" -yyextra->s = yyextra->scanBuf; BEGIN(S_STR); - YY_BREAK -case 4: -YY_RULE_SETUP -#line 76 "scanner.l" -{ - BEGIN(INITIAL); - *yyextra->s = '\0'; - yylval->str = strdup(yyextra->scanBuf); - return STRING; - } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 83 "scanner.l" -{ - /* octal escape sequence */ - unsigned int result; - - (void) sscanf( yytext + 1, "%o", &result ); - - if (result > 0xff) { - scanner_error_extra(yylloc, yyextra, - "Illegal octal escape"); - return ERROR_TOK; - } - - APPEND_S(result); - } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 98 "scanner.l" -{ - scanner_error_extra(yylloc, yyextra, - "Illegal octal escape"); - return ERROR_TOK; - } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 104 "scanner.l" -APPEND_S('\n'); - YY_BREAK -case 8: -YY_RULE_SETUP -#line 105 "scanner.l" -APPEND_S('\t'); - YY_BREAK -case 9: -YY_RULE_SETUP -#line 106 "scanner.l" -APPEND_S('\r'); - YY_BREAK -case 10: -YY_RULE_SETUP -#line 107 "scanner.l" -APPEND_S('\b'); - YY_BREAK -case 11: -YY_RULE_SETUP -#line 108 "scanner.l" -APPEND_S('\f'); - YY_BREAK -case 12: -YY_RULE_SETUP -#line 109 "scanner.l" -APPEND_S('\v'); - YY_BREAK -case 13: -YY_RULE_SETUP -#line 110 "scanner.l" -APPEND_S('\033'); - YY_BREAK -case 14: -YY_RULE_SETUP -#line 112 "scanner.l" -APPEND_S(yytext[0]); - YY_BREAK -case 15: -YY_RULE_SETUP -#line 114 "scanner.l" -{ - /* We don't want the brackets. */ - yytext[yyleng - 1] = '\0'; - yytext++; - yylval->sval = xkb_atom_intern(yyextra->ctx, yytext); - return KEYNAME; - } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 122 "scanner.l" -return XKB_KEYMAP; - YY_BREAK -case 17: -YY_RULE_SETUP -#line 123 "scanner.l" -return XKB_KEYCODES; - YY_BREAK -case 18: -YY_RULE_SETUP -#line 124 "scanner.l" -return XKB_TYPES; - YY_BREAK -case 19: -YY_RULE_SETUP -#line 125 "scanner.l" -return XKB_SYMBOLS; - YY_BREAK -case 20: -YY_RULE_SETUP -#line 126 "scanner.l" -return XKB_COMPATMAP; - YY_BREAK -case 21: -YY_RULE_SETUP -#line 127 "scanner.l" -return XKB_COMPATMAP; - YY_BREAK -case 22: -YY_RULE_SETUP -#line 128 "scanner.l" -return XKB_COMPATMAP; - YY_BREAK -case 23: -YY_RULE_SETUP -#line 129 "scanner.l" -return XKB_COMPATMAP; - YY_BREAK -case 24: -YY_RULE_SETUP -#line 130 "scanner.l" -return XKB_GEOMETRY; - YY_BREAK -case 25: -YY_RULE_SETUP -#line 131 "scanner.l" -return XKB_SEMANTICS; - YY_BREAK -case 26: -YY_RULE_SETUP -#line 132 "scanner.l" -return XKB_LAYOUT; - YY_BREAK -case 27: -YY_RULE_SETUP -#line 133 "scanner.l" -return INCLUDE; - YY_BREAK -case 28: -YY_RULE_SETUP -#line 134 "scanner.l" -return OVERRIDE; - YY_BREAK -case 29: -YY_RULE_SETUP -#line 135 "scanner.l" -return AUGMENT; - YY_BREAK -case 30: -YY_RULE_SETUP -#line 136 "scanner.l" -return REPLACE; - YY_BREAK -case 31: -YY_RULE_SETUP -#line 137 "scanner.l" -return ALTERNATE; - YY_BREAK -case 32: -YY_RULE_SETUP -#line 138 "scanner.l" -return PARTIAL; - YY_BREAK -case 33: -YY_RULE_SETUP -#line 139 "scanner.l" -return DEFAULT; - YY_BREAK -case 34: -YY_RULE_SETUP -#line 140 "scanner.l" -return HIDDEN; - YY_BREAK -case 35: -YY_RULE_SETUP -#line 141 "scanner.l" -return VIRTUAL_MODS; - YY_BREAK -case 36: -YY_RULE_SETUP -#line 142 "scanner.l" -return TYPE; - YY_BREAK -case 37: -YY_RULE_SETUP -#line 143 "scanner.l" -return INTERPRET; - YY_BREAK -case 38: -YY_RULE_SETUP -#line 144 "scanner.l" -return ACTION_TOK; - YY_BREAK -case 39: -YY_RULE_SETUP -#line 145 "scanner.l" -return KEY; - YY_BREAK -case 40: -YY_RULE_SETUP -#line 146 "scanner.l" -return ALIAS; - YY_BREAK -case 41: -YY_RULE_SETUP -#line 147 "scanner.l" -return GROUP; - YY_BREAK -case 42: -YY_RULE_SETUP -#line 148 "scanner.l" -return MODIFIER_MAP; - YY_BREAK -case 43: -YY_RULE_SETUP -#line 149 "scanner.l" -return MODIFIER_MAP; - YY_BREAK -case 44: -YY_RULE_SETUP -#line 150 "scanner.l" -return MODIFIER_MAP; - YY_BREAK -case 45: -YY_RULE_SETUP -#line 151 "scanner.l" -return INDICATOR; - YY_BREAK -case 46: -YY_RULE_SETUP -#line 152 "scanner.l" -return SHAPE; - YY_BREAK -case 47: -YY_RULE_SETUP -#line 153 "scanner.l" -return ROW; - YY_BREAK -case 48: -YY_RULE_SETUP -#line 154 "scanner.l" -return KEYS; - YY_BREAK -case 49: -YY_RULE_SETUP -#line 155 "scanner.l" -return SECTION; - YY_BREAK -case 50: -YY_RULE_SETUP -#line 156 "scanner.l" -return OVERLAY; - YY_BREAK -case 51: -YY_RULE_SETUP -#line 157 "scanner.l" -return TEXT; - YY_BREAK -case 52: -YY_RULE_SETUP -#line 158 "scanner.l" -return OUTLINE; - YY_BREAK -case 53: -YY_RULE_SETUP -#line 159 "scanner.l" -return SOLID; - YY_BREAK -case 54: -YY_RULE_SETUP -#line 160 "scanner.l" -return LOGO; - YY_BREAK -case 55: -YY_RULE_SETUP -#line 161 "scanner.l" -return VIRTUAL; - YY_BREAK -case 56: -YY_RULE_SETUP -#line 162 "scanner.l" -return ALPHANUMERIC_KEYS; - YY_BREAK -case 57: -YY_RULE_SETUP -#line 163 "scanner.l" -return MODIFIER_KEYS; - YY_BREAK -case 58: -YY_RULE_SETUP -#line 164 "scanner.l" -return KEYPAD_KEYS; - YY_BREAK -case 59: -YY_RULE_SETUP -#line 165 "scanner.l" -return FUNCTION_KEYS; - YY_BREAK -case 60: -YY_RULE_SETUP -#line 166 "scanner.l" -return ALTERNATE_GROUP; - YY_BREAK -case 61: -YY_RULE_SETUP -#line 168 "scanner.l" -yylval->str = strdup(yytext); return IDENT; - YY_BREAK -case 62: -#line 171 "scanner.l" -case 63: -YY_RULE_SETUP -#line 171 "scanner.l" -{ - char *end; - yylval->num = strtoul(yytext, &end, 0); - - return INTEGER; - } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 177 "scanner.l" -{ - char *end; - yylval->num = strtod(yytext, &end); - - return FLOAT; - } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 184 "scanner.l" -return EQUALS; - YY_BREAK -case 66: -YY_RULE_SETUP -#line 185 "scanner.l" -return PLUS; - YY_BREAK -case 67: -YY_RULE_SETUP -#line 186 "scanner.l" -return MINUS; - YY_BREAK -case 68: -YY_RULE_SETUP -#line 187 "scanner.l" -return DIVIDE; - YY_BREAK -case 69: -YY_RULE_SETUP -#line 188 "scanner.l" -return TIMES; - YY_BREAK -case 70: -YY_RULE_SETUP -#line 189 "scanner.l" -return OBRACE; - YY_BREAK -case 71: -YY_RULE_SETUP -#line 190 "scanner.l" -return CBRACE; - YY_BREAK -case 72: -YY_RULE_SETUP -#line 191 "scanner.l" -return OPAREN; - YY_BREAK -case 73: -YY_RULE_SETUP -#line 192 "scanner.l" -return CPAREN; - YY_BREAK -case 74: -YY_RULE_SETUP -#line 193 "scanner.l" -return OBRACKET; - YY_BREAK -case 75: -YY_RULE_SETUP -#line 194 "scanner.l" -return CBRACKET; - YY_BREAK -case 76: -YY_RULE_SETUP -#line 195 "scanner.l" -return DOT; - YY_BREAK -case 77: -YY_RULE_SETUP -#line 196 "scanner.l" -return COMMA; - YY_BREAK -case 78: -YY_RULE_SETUP -#line 197 "scanner.l" -return SEMI; - YY_BREAK -case 79: -YY_RULE_SETUP -#line 198 "scanner.l" -return EXCLAM; - YY_BREAK -case 80: -YY_RULE_SETUP -#line 199 "scanner.l" -return INVERT; - YY_BREAK -case 81: -/* rule 81 can match eol */ -YY_RULE_SETUP -#line 201 "scanner.l" - - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(S_STR): -#line 203 "scanner.l" -return END_OF_FILE; - YY_BREAK -case 82: -YY_RULE_SETUP -#line 205 "scanner.l" -return ERROR_TOK; - YY_BREAK -case 83: -YY_RULE_SETUP -#line 207 "scanner.l" -ECHO; - YY_BREAK -#line 1600 "src/xkbcomp/scanner.c" - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yyg->yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * _xkbcommon_lex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( yyscanner ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); - - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yyg->yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_END_OF_FILE: - { - yyg->yy_did_buffer_switch_on_eof = 0; - - if ( _xkbcommon_wrap(yyscanner ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = - yyg->yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( yyscanner ); - - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yyg->yy_c_buf_p = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; - - yy_current_state = yy_get_previous_state( yyscanner ); - - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of _xkbcommon_lex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = yyg->yytext_ptr; - register int number_to_move, i; - int ret_val; - - if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) (yyg->yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - _xkbcommon_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - yyg->yy_n_chars, (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - if ( yyg->yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - _xkbcommon_restart(yyin ,yyscanner); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _xkbcommon_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - yyg->yy_n_chars += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (yyscan_t yyscanner) -{ - register yy_state_type yy_current_state; - register char *yy_cp; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - yy_current_state = yyg->yy_start; - - for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 336 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) -{ - register int yy_is_jam; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ - register char *yy_cp = yyg->yy_c_buf_p; - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 336 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 335); - - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (yyscan_t yyscanner) -#else - static int input (yyscan_t yyscanner) -#endif - -{ - int c; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - *yyg->yy_c_buf_p = yyg->yy_hold_char; - - if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - /* This was really a NUL. */ - *yyg->yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; - ++yyg->yy_c_buf_p; - - switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - _xkbcommon_restart(yyin ,yyscanner); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( _xkbcommon_wrap(yyscanner ) ) - return EOF; - - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(yyscanner); -#else - return input(yyscanner); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = yyg->yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ - *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ - yyg->yy_hold_char = *++yyg->yy_c_buf_p; - - if ( c == '\n' ) - - do{ yylineno++; - yycolumn=0; - }while(0) -; - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * @param yyscanner The scanner object. - * @note This function does not reset the start condition to @c INITIAL . - */ - void _xkbcommon_restart (FILE * input_file , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! YY_CURRENT_BUFFER ){ - _xkbcommon_ensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - _xkbcommon__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); - } - - _xkbcommon__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - _xkbcommon__load_buffer_state(yyscanner ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * @param yyscanner The scanner object. - */ - void _xkbcommon__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* TODO. We should be able to replace this entire function body - * with - * _xkbcommon_pop_buffer_state(); - * _xkbcommon_push_buffer_state(new_buffer); - */ - _xkbcommon_ensure_buffer_stack (yyscanner); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - _xkbcommon__load_buffer_state(yyscanner ); - - /* We don't actually know whether we did this switch during - * EOF (_xkbcommon_wrap()) processing, but the only time this flag - * is looked at is after _xkbcommon_wrap() is called, so it's safe - * to go ahead and always set it. - */ - yyg->yy_did_buffer_switch_on_eof = 1; -} - -static void _xkbcommon__load_buffer_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - yyg->yy_hold_char = *yyg->yy_c_buf_p; -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * @param yyscanner The scanner object. - * @return the allocated buffer state. - */ - YY_BUFFER_STATE _xkbcommon__create_buffer (FILE * file, int size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) _xkbcommon_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in _xkbcommon__create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) _xkbcommon_alloc(b->yy_buf_size + 2 ,yyscanner ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in _xkbcommon__create_buffer()" ); - - b->yy_is_our_buffer = 1; - - _xkbcommon__init_buffer(b,file ,yyscanner); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with _xkbcommon__create_buffer() - * @param yyscanner The scanner object. - */ - void _xkbcommon__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - _xkbcommon_free((void *) b->yy_ch_buf ,yyscanner ); - - _xkbcommon_free((void *) b ,yyscanner ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a _xkbcommon_restart() or at EOF. - */ - static void _xkbcommon__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) - -{ - int oerrno = errno; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - _xkbcommon__flush_buffer(b ,yyscanner); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then _xkbcommon__init_buffer was _probably_ - * called from _xkbcommon_restart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * @param yyscanner The scanner object. - */ - void _xkbcommon__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - _xkbcommon__load_buffer_state(yyscanner ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * @param yyscanner The scanner object. - */ -void _xkbcommon_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (new_buffer == NULL) - return; - - _xkbcommon_ensure_buffer_stack(yyscanner); - - /* This block is copied from _xkbcommon__switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - yyg->yy_buffer_stack_top++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from _xkbcommon__switch_to_buffer. */ - _xkbcommon__load_buffer_state(yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * @param yyscanner The scanner object. - */ -void _xkbcommon_pop_buffer_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (!YY_CURRENT_BUFFER) - return; - - _xkbcommon__delete_buffer(YY_CURRENT_BUFFER ,yyscanner); - YY_CURRENT_BUFFER_LVALUE = NULL; - if (yyg->yy_buffer_stack_top > 0) - --yyg->yy_buffer_stack_top; - - if (YY_CURRENT_BUFFER) { - _xkbcommon__load_buffer_state(yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void _xkbcommon_ensure_buffer_stack (yyscan_t yyscanner) -{ - int num_to_alloc; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (!yyg->yy_buffer_stack) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - yyg->yy_buffer_stack = (struct yy_buffer_state**)_xkbcommon_alloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in _xkbcommon_ensure_buffer_stack()" ); - - memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - yyg->yy_buffer_stack_max = num_to_alloc; - yyg->yy_buffer_stack_top = 0; - return; - } - - if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)_xkbcommon_realloc - (yyg->yy_buffer_stack, - num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in _xkbcommon_ensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); - yyg->yy_buffer_stack_max = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE _xkbcommon__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) _xkbcommon_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in _xkbcommon__scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - _xkbcommon__switch_to_buffer(b ,yyscanner ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to _xkbcommon_lex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * _xkbcommon__scan_bytes() instead. - */ -YY_BUFFER_STATE _xkbcommon__scan_string (yyconst char * yystr , yyscan_t yyscanner) -{ - - return _xkbcommon__scan_bytes(yystr,strlen(yystr) ,yyscanner); -} - -/** Setup the input buffer state to scan the given bytes. The next call to _xkbcommon_lex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE _xkbcommon__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) _xkbcommon_alloc(n ,yyscanner ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in _xkbcommon__scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = _xkbcommon__scan_buffer(buf,n ,yyscanner); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in _xkbcommon__scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = yyg->yy_hold_char; \ - yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ - yyg->yy_hold_char = *yyg->yy_c_buf_p; \ - *yyg->yy_c_buf_p = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the user-defined data for this scanner. - * @param yyscanner The scanner object. - */ -YY_EXTRA_TYPE _xkbcommon_get_extra (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyextra; -} - -/** Get the current line number. - * @param yyscanner The scanner object. - */ -int _xkbcommon_get_lineno (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (! YY_CURRENT_BUFFER) - return 0; - - return yylineno; -} - -/** Get the current column number. - * @param yyscanner The scanner object. - */ -int _xkbcommon_get_column (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (! YY_CURRENT_BUFFER) - return 0; - - return yycolumn; -} - -/** Get the input stream. - * @param yyscanner The scanner object. - */ -FILE *_xkbcommon_get_in (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyin; -} - -/** Get the output stream. - * @param yyscanner The scanner object. - */ -FILE *_xkbcommon_get_out (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyout; -} - -/** Get the length of the current token. - * @param yyscanner The scanner object. - */ -int _xkbcommon_get_leng (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyleng; -} - -/** Get the current token. - * @param yyscanner The scanner object. - */ - -char *_xkbcommon_get_text (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yytext; -} - -/** Set the user-defined data. This data is never touched by the scanner. - * @param user_defined The data to be associated with this scanner. - * @param yyscanner The scanner object. - */ -void _xkbcommon_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyextra = user_defined ; -} - -/** Set the current line number. - * @param line_number - * @param yyscanner The scanner object. - */ -void _xkbcommon_set_lineno (int line_number , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* lineno is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "_xkbcommon_set_lineno called with no buffer" , yyscanner); - - yylineno = line_number; -} - -/** Set the current column. - * @param line_number - * @param yyscanner The scanner object. - */ -void _xkbcommon_set_column (int column_no , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* column is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "_xkbcommon_set_column called with no buffer" , yyscanner); - - yycolumn = column_no; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * @param yyscanner The scanner object. - * @see _xkbcommon__switch_to_buffer - */ -void _xkbcommon_set_in (FILE * in_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyin = in_str ; -} - -void _xkbcommon_set_out (FILE * out_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyout = out_str ; -} - -int _xkbcommon_get_debug (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yy_flex_debug; -} - -void _xkbcommon_set_debug (int bdebug , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yy_flex_debug = bdebug ; -} - -/* Accessor methods for yylval and yylloc */ - -YYSTYPE * _xkbcommon_get_lval (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yylval; -} - -void _xkbcommon_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yylval = yylval_param; -} - -YYLTYPE *_xkbcommon_get_lloc (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yylloc; -} - -void _xkbcommon_set_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yylloc = yylloc_param; -} - -/* User-visible API */ - -/* _xkbcommon_lex_init is special because it creates the scanner itself, so it is - * the ONLY reentrant function that doesn't take the scanner as the last argument. - * That's why we explicitly handle the declaration, instead of using our macros. - */ - -int _xkbcommon_lex_init(yyscan_t* ptr_yy_globals) - -{ - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) _xkbcommon_alloc ( sizeof( struct yyguts_t ), NULL ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - return yy_init_globals ( *ptr_yy_globals ); -} - -/* _xkbcommon_lex_init_extra has the same functionality as _xkbcommon_lex_init, but follows the - * convention of taking the scanner as the last argument. Note however, that - * this is a *pointer* to a scanner, as it will be allocated by this call (and - * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to _xkbcommon_alloc in - * the yyextra field. - */ - -int _xkbcommon_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) - -{ - struct yyguts_t dummy_yyguts; - - _xkbcommon_set_extra (yy_user_defined, &dummy_yyguts); - - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) _xkbcommon_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - /* By setting to 0xAA, we expose bugs in - yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - _xkbcommon_set_extra (yy_user_defined, *ptr_yy_globals); - - return yy_init_globals ( *ptr_yy_globals ); -} - -static int yy_init_globals (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from _xkbcommon_lex_destroy(), so don't allocate here. - */ - - yyg->yy_buffer_stack = 0; - yyg->yy_buffer_stack_top = 0; - yyg->yy_buffer_stack_max = 0; - yyg->yy_c_buf_p = (char *) 0; - yyg->yy_init = 0; - yyg->yy_start = 0; - - yyg->yy_start_stack_ptr = 0; - yyg->yy_start_stack_depth = 0; - yyg->yy_start_stack = NULL; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; -#else - yyin = (FILE *) 0; - yyout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * _xkbcommon_lex_init() - */ - return 0; -} - -/* _xkbcommon_lex_destroy is for both reentrant and non-reentrant scanners. */ -int _xkbcommon_lex_destroy (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - _xkbcommon__delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); - YY_CURRENT_BUFFER_LVALUE = NULL; - _xkbcommon_pop_buffer_state(yyscanner); - } - - /* Destroy the stack itself. */ - _xkbcommon_free(yyg->yy_buffer_stack ,yyscanner); - yyg->yy_buffer_stack = NULL; - - /* Destroy the start condition stack. */ - _xkbcommon_free(yyg->yy_start_stack ,yyscanner ); - yyg->yy_start_stack = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * _xkbcommon_lex() is called, initialization will occur. */ - yy_init_globals( yyscanner); - - /* Destroy the main struct (reentrant only). */ - _xkbcommon_free ( yyscanner , yyscanner ); - yyscanner = NULL; - return 0; -} - /* - * Internal utility routines. + * Copyright © 2012 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *_xkbcommon_alloc (yy_size_t size , yyscan_t yyscanner) -{ - return (void *) malloc( size ); -} - -void *_xkbcommon_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} +#include "xkbcomp-priv.h" +#include "parser-priv.h" +#include "scanner-utils.h" -void _xkbcommon_free (void * ptr , yyscan_t yyscanner) +static void +scanner_log(enum xkb_log_level level, struct scanner *s, const char *msg) { - free( (char *) ptr ); /* see _xkbcommon_realloc() for (char *) cast */ + xkb_log(s->ctx, level, 0, "%s:%d:%d: %s\n", s->file_name, + s->token_line, s->token_column, msg); } -#define YYTABLES_NAME "yytables" - -#line 207 "scanner.l" - - - -#pragma GCC diagnostic pop - -static void -scanner_error_extra(struct YYLTYPE *loc, struct scanner_extra *extra, - const char *msg) +int +scanner_error(struct scanner *s, const char *msg) { - log_err(extra->ctx, "%s: line %d of %s\n", msg, - loc->first_line, - extra->file_name ? extra->file_name : "(unknown)"); + scanner_log(XKB_LOG_LEVEL_ERROR, s, msg); + return ERROR_TOK; } void -scanner_error(struct YYLTYPE *loc, void *scanner, const char *msg) +scanner_warn(struct scanner *s, const char *msg) { - struct scanner_extra *extra = _xkbcommon_get_extra(scanner); - scanner_error_extra(loc, extra, msg); + scanner_log(XKB_LOG_LEVEL_WARNING, s, msg); } static bool -init_scanner(yyscan_t *scanner, struct scanner_extra *extra, - struct xkb_context *ctx, const char *file_name) +number(struct scanner *s, int64_t *out, int *out_tok) { - memset(extra, 0, sizeof(*extra)); + bool is_float = false, is_hex = false; + const char *start = s->s + s->pos; + char *end; - if (_xkbcommon_lex_init_extra(extra,scanner) != 0) + if (lit(s, "0x")) { + while (is_xdigit(peek(s))) next(s); + is_hex = true; + } + else { + while (is_digit(peek(s))) next(s); + is_float = chr(s, '.'); + while (is_digit(peek(s))) next(s); + } + if (s->s + s->pos == start) return false; - extra->ctx = ctx; - extra->file_name = file_name; - + errno = 0; + if (is_hex) + *out = strtoul(start, &end, 16); + else if (is_float) + *out = strtod(start, &end); + else + *out = strtoul(start, &end, 10); + if (errno != 0 || s->s + s->pos != end) + *out_tok = ERROR_TOK; + else + *out_tok = (is_float ? FLOAT : INTEGER); return true; } -static void -clear_scanner(yyscan_t scanner) +int +_xkbcommon_lex(YYSTYPE *yylval, struct scanner *s) { - _xkbcommon_lex_destroy(scanner); -} + int tok; -XkbFile * -XkbParseString(struct xkb_context *ctx, const char *string, - const char *file_name) -{ - yyscan_t scanner; - struct scanner_extra extra; - YY_BUFFER_STATE state; - XkbFile *xkb_file; +skip_more_whitespace_and_comments: + /* Skip spaces. */ + while (is_space(peek(s))) next(s); - if (!init_scanner(&scanner, &extra, ctx, file_name)) - return NULL; + /* Skip comments. */ + if (lit(s, "//") || chr(s, '#')) { + while (!eof(s) && !eol(s)) next(s); + goto skip_more_whitespace_and_comments; + } - state = _xkbcommon__scan_string(string,scanner); + /* See if we're done. */ + if (eof(s)) return END_OF_FILE; + + /* New token. */ + s->token_line = s->line; + s->token_column = s->column; + s->buf_pos = 0; + + /* String literal. */ + if (chr(s, '\"')) { + while (!eof(s) && !eol(s) && peek(s) != '\"') { + if (chr(s, '\\')) { + uint8_t o; + if (chr(s, '\\')) buf_append(s, '\\'); + else if (chr(s, 'n')) buf_append(s, '\n'); + else if (chr(s, 't')) buf_append(s, '\t'); + else if (chr(s, 'r')) buf_append(s, '\r'); + else if (chr(s, 'b')) buf_append(s, '\b'); + else if (chr(s, 'f')) buf_append(s, '\f'); + else if (chr(s, 'v')) buf_append(s, '\v'); + else if (chr(s, 'e')) buf_append(s, '\033'); + else if (oct(s, &o)) buf_append(s, (char) o); + else { + scanner_warn(s, "unknown escape sequence in string literal"); + /* Ignore. */ + } + } else { + buf_append(s, next(s)); + } + } + if (!buf_append(s, '\0') || !chr(s, '\"')) + return scanner_error(s, "unterminated string literal"); + yylval->str = strdup(s->buf); + if (!yylval->str) + return scanner_error(s, "scanner out of memory"); + return STRING; + } - xkb_file = parse(ctx, scanner, NULL); + /* Key name literal. */ + if (chr(s, '<')) { + while (is_graph(peek(s)) && peek(s) != '>') + buf_append(s, next(s)); + if (!buf_append(s, '\0') || !chr(s, '>')) + return scanner_error(s, "unterminated key name literal"); + /* Empty key name literals are allowed. */ + yylval->sval = xkb_atom_intern(s->ctx, s->buf, s->buf_pos - 1); + return KEYNAME; + } - _xkbcommon__delete_buffer(state,scanner); - clear_scanner(scanner); + /* Operators and punctuation. */ + if (chr(s, ';')) return SEMI; + if (chr(s, '{')) return OBRACE; + if (chr(s, '}')) return CBRACE; + if (chr(s, '=')) return EQUALS; + if (chr(s, '[')) return OBRACKET; + if (chr(s, ']')) return CBRACKET; + if (chr(s, '(')) return OPAREN; + if (chr(s, ')')) return CPAREN; + if (chr(s, '.')) return DOT; + if (chr(s, ',')) return COMMA; + if (chr(s, '+')) return PLUS; + if (chr(s, '-')) return MINUS; + if (chr(s, '*')) return TIMES; + if (chr(s, '/')) return DIVIDE; + if (chr(s, '!')) return EXCLAM; + if (chr(s, '~')) return INVERT; + + /* Identifier. */ + if (is_alpha(peek(s)) || peek(s) == '_') { + s->buf_pos = 0; + while (is_alnum(peek(s)) || peek(s) == '_') + buf_append(s, next(s)); + if (!buf_append(s, '\0')) + return scanner_error(s, "identifier too long"); + + /* Keyword. */ + tok = keyword_to_token(s->buf); + if (tok != -1) return tok; + + yylval->str = strdup(s->buf); + if (!yylval->str) + return scanner_error(s, "scanner out of memory"); + return IDENT; + } - return xkb_file; + /* Number literal (hexadecimal / decimal / float). */ + if (number(s, &yylval->num, &tok)) { + if (tok == ERROR_TOK) + return scanner_error(s, "malformed number literal"); + return tok; + } + + return scanner_error(s, "unrecognized token"); } -/* - * _xkbcommon__scan_buffer() requires the last two bytes of \buf to be 0. These two bytes - * are not scanned. Other zero bytes in the buffer are scanned normally, though. - * Due to these terminating zeroes, \length must be greater than 2. - * Furthermore, the buffer must be writable and you cannot make any assumptions - * about it after the scanner finished. - * All this must be guaranteed by the caller of this function! - */ XkbFile * -XkbParseBuffer(struct xkb_context *ctx, char *buf, size_t length, - const char *file_name) +XkbParseString(struct xkb_context *ctx, const char *string, size_t len, + const char *file_name, const char *map) { - yyscan_t scanner; - struct scanner_extra extra; - YY_BUFFER_STATE state; - XkbFile *xkb_file; - - if (!init_scanner(&scanner, &extra, ctx, file_name)) - return NULL; - - xkb_file = NULL; - state = _xkbcommon__scan_buffer(buf,length,scanner); - if (state) { - xkb_file = parse(ctx, scanner, NULL); - _xkbcommon__delete_buffer(state,scanner); - } - - clear_scanner(scanner); - - return xkb_file; + struct scanner scanner; + scanner_init(&scanner, ctx, string, len, file_name); + return parse(ctx, &scanner, map); } XkbFile * XkbParseFile(struct xkb_context *ctx, FILE *file, const char *file_name, const char *map) { - yyscan_t scanner; - struct scanner_extra extra; - YY_BUFFER_STATE state; + bool ok; XkbFile *xkb_file; + const char *string; + size_t size; - if (!init_scanner(&scanner, &extra, ctx, file_name)) + ok = map_file(file, &string, &size); + if (!ok) { + log_err(ctx, "Couldn't read XKB file %s: %s\n", + file_name, strerror(errno)); return NULL; + } - state = _xkbcommon__create_buffer(file,YY_BUF_SIZE,scanner); - _xkbcommon__switch_to_buffer(state,scanner); - - xkb_file = parse(ctx, scanner, map); - - _xkbcommon__delete_buffer(state,scanner); - clear_scanner(scanner); - + xkb_file = XkbParseString(ctx, string, size, file_name, map); + unmap_file(string, size); return xkb_file; } - diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c b/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c index a2970f5004..56cce431da 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c @@ -143,7 +143,7 @@ InitKeyInfo(struct xkb_context *ctx, KeyInfo *keyi) { memset(keyi, 0, sizeof(*keyi)); keyi->merge = MERGE_OVERRIDE; - keyi->name = xkb_atom_intern(ctx, "*"); + keyi->name = xkb_atom_intern_literal(ctx, "*"); keyi->out_of_range_group_action = RANGE_WRAP; } @@ -177,7 +177,7 @@ typedef struct { KeyInfo default_key; ActionsInfo *actions; darray(xkb_atom_t) group_names; - darray(ModMapEntry) modMaps; + darray(ModMapEntry) modmaps; struct xkb_keymap *keymap; } SymbolsInfo; @@ -203,7 +203,7 @@ ClearSymbolsInfo(SymbolsInfo *info) ClearKeyInfo(keyi); darray_free(info->keys); darray_free(info->group_names); - darray_free(info->modMaps); + darray_free(info->modmaps); ClearKeyInfo(&info->default_key); } @@ -437,7 +437,7 @@ AddModMapEntry(SymbolsInfo *info, ModMapEntry *new) ModMapEntry *old; bool clobber = (new->merge != MERGE_AUGMENT); - darray_foreach(old, info->modMaps) { + darray_foreach(old, info->modmaps) { xkb_mod_index_t use, ignore; if ((new->haveSymbol != old->haveSymbol) || @@ -470,7 +470,7 @@ AddModMapEntry(SymbolsInfo *info, ModMapEntry *new) return true; } - darray_append(info->modMaps, *new); + darray_append(info->modmaps, *new); return true; } @@ -517,7 +517,7 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from, into->errorCount++; } - darray_foreach(mm, from->modMaps) { + darray_foreach(mm, from->modmaps) { mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge); if (!AddModMapEntry(into, mm)) into->errorCount++; @@ -626,30 +626,6 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, return true; } -bool -LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn) -{ - xkb_keysym_t sym; - - if (!str || istreq(str, "any") || istreq(str, "nosymbol")) { - *sym_rtrn = XKB_KEY_NoSymbol; - return 1; - } - - if (istreq(str, "none") || istreq(str, "voidsymbol")) { - *sym_rtrn = XKB_KEY_VoidSymbol; - return 1; - } - - sym = xkb_keysym_from_name(str, 0); - if (sym != XKB_KEY_NoSymbol) { - *sym_rtrn = sym; - return 1; - } - - return 0; -} - static bool AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, ExprDef *value) @@ -670,11 +646,11 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, return true; } - if (value->op != EXPR_KEYSYM_LIST) { + if (value->expr.op != EXPR_KEYSYM_LIST) { log_err(info->keymap->ctx, "Expected a list of symbols, found %s; " "Ignoring symbols for group %u of %s\n", - expr_op_type_to_string(value->op), ndx + 1, + expr_op_type_to_string(value->expr.op), ndx + 1, KeyInfoText(info, keyi)); return false; } @@ -687,7 +663,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, return false; } - nLevels = darray_size(value->value.list.symsMapIndex); + nLevels = darray_size(value->keysym_list.symsMapIndex); if (darray_size(groupi->levels) < nLevels) darray_resize0(groupi->levels, nLevels); @@ -697,34 +673,14 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, unsigned int sym_index; struct xkb_level *leveli = &darray_item(groupi->levels, i); - sym_index = darray_item(value->value.list.symsMapIndex, i); - leveli->num_syms = darray_item(value->value.list.symsNumEntries, i); + sym_index = darray_item(value->keysym_list.symsMapIndex, i); + leveli->num_syms = darray_item(value->keysym_list.symsNumEntries, i); if (leveli->num_syms > 1) leveli->u.syms = calloc(leveli->num_syms, sizeof(*leveli->u.syms)); for (j = 0; j < leveli->num_syms; j++) { - char *sym_name = darray_item(value->value.list.syms, - sym_index + j); - xkb_keysym_t keysym; - - if (!LookupKeysym(sym_name, &keysym)) { - const char *group_name = "unnamed"; - - if (ndx < darray_size(info->group_names) && - darray_item(info->group_names, ndx)) - group_name = xkb_atom_text(info->keymap->ctx, - darray_item(info->group_names, - ndx)); - - log_warn(info->keymap->ctx, - "Could not resolve keysym %s for key %s, group %u (%s), level %u\n", - sym_name, KeyInfoText(info, keyi), ndx + 1, - group_name, i); - - ClearLevelInfo(leveli); - leveli->num_syms = 0; - break; - } + xkb_keysym_t keysym = darray_item(value->keysym_list.syms, + sym_index + j); if (leveli->num_syms == 1) { if (keysym == XKB_KEY_NoSymbol) @@ -750,7 +706,6 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, GroupInfo *groupi; unsigned int nActs; ExprDef *act; - union xkb_action *toAct; if (!GetGroupIndex(info, keyi, arrayNdx, ACTIONS, &ndx)) return false; @@ -762,11 +717,11 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, return true; } - if (value->op != EXPR_ACTION_LIST) { + if (value->expr.op != EXPR_ACTION_LIST) { log_wsgo(info->keymap->ctx, "Bad expression type (%d) for action list value; " "Ignoring actions for group %u of %s\n", - value->op, ndx, KeyInfoText(info, keyi)); + value->expr.op, ndx, KeyInfoText(info, keyi)); return false; } @@ -778,7 +733,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, } nActs = 0; - for (act = value->value.child; act; act = (ExprDef *) act->common.next) + for (act = value->unary.child; act; act = (ExprDef *) act->common.next) nActs++; if (darray_size(groupi->levels) < nActs) @@ -786,9 +741,9 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, groupi->defined |= GROUP_FIELD_ACTS; - act = value->value.child; + act = value->unary.child; for (i = 0; i < nActs; i++) { - toAct = &darray_item(groupi->levels, i).action; + union xkb_action *toAct = &darray_item(groupi->levels, i).action; if (!HandleActionDef(act, info->keymap, toAct, info->actions)) log_err(info->keymap->ctx, @@ -866,7 +821,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field, log_err(info->keymap->ctx, "Expected a virtual modifier mask, found %s; " "Ignoring virtual modifiers definition for key %s\n", - expr_op_type_to_string(value->op), + expr_op_type_to_string(value->expr.op), KeyInfoText(info, keyi)); } } @@ -1082,7 +1037,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi) ExprDef *arrayNdx; for (; def; def = (VarDef *) def->common.next) { - if (def->name && def->name->op == EXPR_FIELD_REF) { + if (def->name && def->name->expr.op == EXPR_FIELD_REF) { log_err(info->keymap->ctx, "Cannot set a global default value from within a key statement; " "Move statements to the global file scope\n"); @@ -1090,7 +1045,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi) } if (!def->name) { - if (!def->value || def->value->op == EXPR_KEYSYM_LIST) + if (!def->value || def->value->expr.op == EXPR_KEYSYM_LIST) field = "symbols"; else field = "actions"; @@ -1158,7 +1113,7 @@ HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt) keyi.merge = stmt->merge; keyi.name = stmt->keyName; - if (!HandleSymbolsBody(info, (VarDef *) stmt->symbols, &keyi)) { + if (!HandleSymbolsBody(info, stmt->symbols, &keyi)) { info->errorCount++; return false; } @@ -1196,13 +1151,15 @@ HandleModMapDef(SymbolsInfo *info, ModMapDef *def) ok = true; tmp.modifier = ndx; + tmp.merge = def->merge; for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) { xkb_keysym_t sym; - if (key->op == EXPR_VALUE && key->value_type == EXPR_TYPE_KEYNAME) { + if (key->expr.op == EXPR_VALUE && + key->expr.value_type == EXPR_TYPE_KEYNAME) { tmp.haveSymbol = false; - tmp.u.keyName = key->value.keyName; + tmp.u.keyName = key->key_name.key_name; } else if (ExprResolveKeySym(ctx, key, &sym)) { tmp.haveSymbol = true; @@ -1248,7 +1205,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge) break; default: log_err(info->keymap->ctx, - "Interpretation files may not include other types; " + "Symbols files may not include other types; " "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; @@ -1339,19 +1296,19 @@ FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi) darray_item(groupi->levels, level).u.syms[0]) if (width == 1 || width <= 0) - return xkb_atom_intern(ctx, "ONE_LEVEL"); + return xkb_atom_intern_literal(ctx, "ONE_LEVEL"); sym0 = GET_SYM(0); sym1 = GET_SYM(1); if (width == 2) { if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1)) - return xkb_atom_intern(ctx, "ALPHABETIC"); + return xkb_atom_intern_literal(ctx, "ALPHABETIC"); if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1)) - return xkb_atom_intern(ctx, "KEYPAD"); + return xkb_atom_intern_literal(ctx, "KEYPAD"); - return xkb_atom_intern(ctx, "TWO_LEVEL"); + return xkb_atom_intern_literal(ctx, "TWO_LEVEL"); } if (width <= 4) { @@ -1360,15 +1317,15 @@ FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi) sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol); if (xkb_keysym_is_lower(sym2) && xkb_keysym_is_upper(sym3)) - return xkb_atom_intern(ctx, "FOUR_LEVEL_ALPHABETIC"); + return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_ALPHABETIC"); - return xkb_atom_intern(ctx, "FOUR_LEVEL_SEMIALPHABETIC"); + return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_SEMIALPHABETIC"); } if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1)) - return xkb_atom_intern(ctx, "FOUR_LEVEL_KEYPAD"); + return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_KEYPAD"); - return xkb_atom_intern(ctx, "FOUR_LEVEL"); + return xkb_atom_intern_literal(ctx, "FOUR_LEVEL"); } return XKB_ATOM_NONE; @@ -1570,9 +1527,9 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info) { KeyInfo *keyi; ModMapEntry *mm; - struct xkb_key *key; keymap->symbols_section_name = strdup_safe(info->name); + XkbEscapeMapName(keymap->symbols_section_name); keymap->num_group_names = darray_size(info->group_names); keymap->group_names = darray_mem(info->group_names, 0); @@ -1583,6 +1540,8 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info) info->errorCount++; if (xkb_context_get_log_verbosity(keymap->ctx) > 3) { + struct xkb_key *key; + xkb_foreach_key(key, keymap) { if (key->name == XKB_ATOM_NONE) continue; @@ -1594,7 +1553,7 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info) } } - darray_foreach(mm, info->modMaps) + darray_foreach(mm, info->modmaps) if (!CopyModMapDef(info, mm)) info->errorCount++; @@ -1618,9 +1577,6 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap, HandleSymbolsFile(&info, file, merge); - if (darray_empty(info.keys)) - goto err_info; - if (info.errorCount != 0) goto err_info; diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/types.c b/src/3rdparty/xkbcommon/src/xkbcomp/types.c index 1eb1b73205..5b7ccbb4db 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/types.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/types.c @@ -197,16 +197,6 @@ ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type, TypeTxt(info, type), wanted); } -static inline bool -ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs) -{ - log_err(info->keymap->ctx, - "Key type \"%s\" has %d levels, must have %d; " - "Illegal type definition ignored\n", - type, has, needs); - return false; -} - /***====================================================================***/ static void @@ -775,6 +765,7 @@ static bool CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info) { keymap->types_section_name = strdup_safe(info->name); + XkbEscapeMapName(keymap->types_section_name); keymap->num_types = darray_size(info->types); if (keymap->num_types == 0) @@ -793,7 +784,7 @@ CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info) type->num_levels = 1; type->entries = NULL; type->num_entries = 0; - type->name = xkb_atom_intern(keymap->ctx, "default"); + type->name = xkb_atom_intern_literal(keymap->ctx, "default"); type->level_names = NULL; return true; diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-priv.h b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-priv.h index 4d421b5f2f..6cb774da17 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-priv.h +++ b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-priv.h @@ -45,12 +45,9 @@ XkbParseFile(struct xkb_context *ctx, FILE *file, const char *file_name, const char *map); XkbFile * -XkbParseString(struct xkb_context *ctx, const char *string, - const char *file_name); - -XkbFile * -XkbParseBuffer(struct xkb_context *ctx, char *buf, size_t length, - const char *file_name); +XkbParseString(struct xkb_context *ctx, + const char *string, size_t len, + const char *file_name, const char *map); void FreeXkbFile(XkbFile *file); @@ -79,9 +76,6 @@ bool CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge); -bool -LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn); - /***====================================================================***/ static inline bool diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp.c b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp.c index b9a1b5ffa6..007e3f73e8 100644 --- a/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp.c +++ b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp.c @@ -97,12 +97,13 @@ text_v1_keymap_new_from_names(struct xkb_keymap *keymap, } static bool -text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string) +text_v1_keymap_new_from_string(struct xkb_keymap *keymap, + const char *string, size_t len) { bool ok; XkbFile *xkb_file; - xkb_file = XkbParseString(keymap->ctx, string, "(input string)"); + xkb_file = XkbParseString(keymap->ctx, string, len, "(input string)", NULL); if (!xkb_file) { log_err(keymap->ctx, "Failed to parse input xkb string\n"); return NULL; @@ -113,38 +114,6 @@ text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string) return ok; } -static bool -text_v1_keymap_new_from_buffer(struct xkb_keymap *keymap, - const char *buffer, size_t length) -{ - bool ok; - XkbFile *xkb_file; - char *buf; - - buf = malloc(length + 2); - if (!buf) { - log_err(keymap->ctx, "Cannot allocate memory for keymap\n"); - return NULL; - } - - /* yy_scan_buffer requires two terminating zero bytes */ - memcpy(buf, buffer, length); - buf[length] = 0; - buf[length + 1] = 0; - - xkb_file = XkbParseBuffer(keymap->ctx, buf, length + 2, "input"); - if (!xkb_file) { - log_err(keymap->ctx, "Failed to parse input xkb file\n"); - free(buf); - return NULL; - } - - ok = compile_keymap_file(keymap, xkb_file); - FreeXkbFile(xkb_file); - free(buf); - return ok; -} - static bool text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file) { @@ -165,7 +134,6 @@ text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file) const struct xkb_keymap_format_ops text_v1_keymap_format_ops = { .keymap_new_from_names = text_v1_keymap_new_from_names, .keymap_new_from_string = text_v1_keymap_new_from_string, - .keymap_new_from_buffer = text_v1_keymap_new_from_buffer, .keymap_new_from_file = text_v1_keymap_new_from_file, .keymap_get_as_string = text_v1_keymap_get_as_string, }; diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h index 253ea59ceb..69c582e45f 100644 --- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h +++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h @@ -418,6 +418,12 @@ SOFTWARE. #define XKB_KEY_dead_belowcomma 0xfe6e #define XKB_KEY_dead_currency 0xfe6f +/* extra dead elements for German T3 layout */ +#define XKB_KEY_dead_lowline 0xfe90 +#define XKB_KEY_dead_aboveverticalline 0xfe91 +#define XKB_KEY_dead_belowverticalline 0xfe92 +#define XKB_KEY_dead_longsolidusoverlay 0xfe93 + /* dead vowels for universal syllable entry */ #define XKB_KEY_dead_a 0xfe80 #define XKB_KEY_dead_A 0xfe81 @@ -2652,6 +2658,8 @@ SOFTWARE. #define XKB_KEY_XF86TouchpadOn 0x1008FFB0 /* The touchpad got switched on */ #define XKB_KEY_XF86TouchpadOff 0x1008FFB1 /* The touchpad got switched off */ +#define XKB_KEY_XF86AudioMicMute 0x1008FFB2 /* Mute the Mic from the system */ + /* Keys for special action keys (hot keys) */ /* Virtual terminals on some operating systems */ #define XKB_KEY_XF86Switch_VT_1 0x1008FE01 diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-names.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-names.h index db071d8a2a..ecb551ff10 100644 --- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-names.h +++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-names.h @@ -35,6 +35,7 @@ #define XKB_MOD_NAME_CAPS "Lock" #define XKB_MOD_NAME_CTRL "Control" #define XKB_MOD_NAME_ALT "Mod1" +#define XKB_MOD_NAME_NUM "Mod2" #define XKB_MOD_NAME_LOGO "Mod4" #define XKB_LED_NAME_CAPS "Caps Lock" diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h new file mode 100644 index 0000000000..4ec9b649c7 --- /dev/null +++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h @@ -0,0 +1,166 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _XKBCOMMON_X11_H +#define _XKBCOMMON_X11_H + +#include +#include + +/** + * @file + * libxkbcommon-x11 API - Additional X11 support for xkbcommon. + */ + +/** + * @defgroup x11 X11 support + * Additional X11 support for xkbcommon. + * + * @{ + */ + +/** + * The minimal compatible major version of the XKB X11 extension which + * this library can use. + */ +#define XKB_X11_MIN_MAJOR_XKB_VERSION 1 +/** + * The minimal compatible minor version of the XKB X11 extension which + * this library can use (for the minimal major version). + */ +#define XKB_X11_MIN_MINOR_XKB_VERSION 0 + +/** Flags for the xkb_x11_setup_xkb_extension() function. */ +enum xkb_x11_setup_xkb_extension_flags { + /** Do not apply any flags. */ + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS = 0 +}; + +/** + * Setup the XKB X11 extension for this X client. + * + * The xkbcommon-x11 library uses various XKB requests. Before doing so, + * an X client must notify the server that it will be using the extension. + * This function (or an XCB equivalent) must be called before any other + * function in this library is used. + * + * Some X servers may not support or disable the XKB extension. If you + * want to support such servers, you need to use a different fallback. + * + * You may call this function several times; it is idempotent. + * + * @param connection + * An XCB connection to the X server. + * @param major_xkb_version, minor_xkb_version + * The XKB extension version to request. To operate correctly, you + * must have (major_xkb_version, minor_xkb_version) >= + * (XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION), + * though this is not enforced. + * @param flags + * Optional flags, or 0. + * @param[out] major_xkb_version_out, minor_xkb_version_out + * Backfilled with the compatible XKB extension version numbers picked + * by the server. Can be NULL. + * @param[out] base_event_out + * Backfilled with the XKB base (also known as first) event code, needed + * to distinguish XKB events. Can be NULL. + * @param[out] base_error_out + * Backfilled with the XKB base (also known as first) error code, needed + * to distinguish XKB errors. Can be NULL. + * + * @returns 1 on success, or 0 on failure. + */ +int +xkb_x11_setup_xkb_extension(xcb_connection_t *connection, + uint16_t major_xkb_version, + uint16_t minor_xkb_version, + enum xkb_x11_setup_xkb_extension_flags flags, + uint16_t *major_xkb_version_out, + uint16_t *minor_xkb_version_out, + uint8_t *base_event_out, + uint8_t *base_error_out); + +/** + * Get the keyboard device ID of the core X11 keyboard. + * + * @param connection An XCB connection to the X server. + * + * @returns A device ID which may be used with other xkb_x11_* functions, + * or -1 on failure. + */ +int32_t +xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection); + +/** + * Create a keymap from an X11 keyboard device. + * + * This function queries the X server with various requests, fetches the + * details of the active keymap on a keyboard device, and creates an + * xkb_keymap from these details. + * + * @param context + * The context in which to create the keymap. + * @param connection + * An XCB connection to the X server. + * @param device_id + * An XInput 1 device ID (in the range 0-255) with input class KEY. + * Passing values outside of this range is an error. + * @param flags + * Optional flags for the keymap, or 0. + * + * @returns A keymap retrieved from the X server, or NULL on failure. + * + * @memberof xkb_keymap + */ +struct xkb_keymap * +xkb_x11_keymap_new_from_device(struct xkb_context *context, + xcb_connection_t *connection, + int32_t device_id, + enum xkb_keymap_compile_flags flags); + +/** + * Create a new keyboard state object from an X11 keyboard device. + * + * This function is the same as xkb_state_new(), only pre-initialized + * with the state of the device at the time this function is called. + * + * @param keymap + * The keymap for which to create the state. + * @param connection + * An XCB connection to the X server. + * @param device_id + * An XInput 1 device ID (in the range 0-255) with input class KEY. + * Passing values outside of this range is an error. + * + * @returns A new keyboard state object, or NULL on failure. + * + * @memberof xkb_state + */ +struct xkb_state * +xkb_x11_state_new_from_device(struct xkb_keymap *keymap, + xcb_connection_t *connection, + int32_t device_id); + +/** @} */ + +#endif diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h index a2aecfbb2a..cc9262ff89 100644 --- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h +++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h @@ -197,7 +197,7 @@ typedef uint32_t xkb_keysym_t; * layout is active. These may be different alphabets, different key * arrangements, etc. * - * Layout indexes are consecutive. The first layout has index 0. + * Layout indices are consecutive. The first layout has index 0. * * Each layout is not required to have a name, and the names are not * guaranteed to be unique (though they are usually provided and unique). @@ -209,13 +209,20 @@ typedef uint32_t xkb_keysym_t; * @sa xkb_keymap_num_layouts() xkb_keymap_num_layouts_for_key() */ typedef uint32_t xkb_layout_index_t; -/** A mask of layout indexes. */ +/** A mask of layout indices. */ typedef uint32_t xkb_layout_mask_t; /** * Index of a shift level. * - * @todo Explain what are shift levels. + * Any key, in any layout, can have several shift levels. Each + * shift level can assign different keysyms to the key. The shift level + * to use is chosen according to the current keyboard state; for example, + * if no keys are pressed, the first level may be used; if the Left Shift + * key is pressed, the second; if Num Lock is pressed, the third; and + * many such combinations are possible (see xkb_mod_index_t). + * + * Level indices are consecutive. The first level has index 0. */ typedef uint32_t xkb_level_index_t; @@ -233,7 +240,7 @@ typedef uint32_t xkb_level_index_t; * consulted; this detemines the correct shift level to use within the * currently active layout (see xkb_level_index_t). * - * Modifier indexes are consecutive. The first modifier has index 0. + * Modifier indices are consecutive. The first modifier has index 0. * * Each modifier must have a name, and the names are unique. Therefore, it * is safe to use the name as a unique identifier for a modifier. The names @@ -243,15 +250,17 @@ typedef uint32_t xkb_level_index_t; * @sa xkb_keymap_num_mods() */ typedef uint32_t xkb_mod_index_t; -/** A mask of modifier indexes. */ +/** A mask of modifier indices. */ typedef uint32_t xkb_mod_mask_t; /** * Index of a keyboard LED. * - * @todo Explain what are LEDs. + * LEDs are logical objects which may be @e active or @e inactive. They + * typically correspond to the lights on the keyboard. Their state is + * determined by the current keyboard state. * - * LED indexes are non-consecutive. The first LED has index 0. + * LED indices are non-consecutive. The first LED has index 0. * * Each LED must have a name, and the names are unique. Therefore, * it is safe to use the name as a unique identifier for a LED. The names @@ -261,7 +270,7 @@ typedef uint32_t xkb_mod_mask_t; * @warning A given keymap may specify an exact index for a given LED. * Therefore, LED indexing is not necessarily sequential, as opposed to * modifiers and layouts. This means that when iterating over the LEDs - * in a keymap using e.g. xkb_keymap_num_leds(), some indexes might be + * in a keymap using e.g. xkb_keymap_num_leds(), some indices might be * invalid. Given such an index, functions like xkb_keymap_led_get_name() * will return NULL, and xkb_state_led_index_is_active() will return -1. * @@ -270,7 +279,7 @@ typedef uint32_t xkb_mod_mask_t; * @sa xkb_keymap_num_leds() */ typedef uint32_t xkb_led_index_t; -/** A mask of LED indexes. */ +/** A mask of LED indices. */ typedef uint32_t xkb_led_mask_t; #define XKB_KEYCODE_INVALID (0xffffffff) @@ -351,6 +360,8 @@ xkb_keysym_get_name(xkb_keysym_t keysym, char *buffer, size_t size); /** Flags for xkb_keysym_from_name(). */ enum xkb_keysym_flags { + /** Do not apply any flags. */ + XKB_KEYSYM_NO_FLAGS = 0, /** Find keysym by case-insensitive search. */ XKB_KEYSYM_CASE_INSENSITIVE = (1 << 0) }; @@ -416,6 +427,8 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym); /** Flags for context creation. */ enum xkb_context_flags { + /** Do not apply any context flags. */ + XKB_CONTEXT_NO_FLAGS = 0, /** Create this context with an empty include path. */ XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0), /** Don't take RMLVO names from the environment. */ @@ -667,6 +680,8 @@ xkb_context_set_log_fn(struct xkb_context *context, /** Flags for keymap compilation. */ enum xkb_keymap_compile_flags { + /** Do not apply any flags. */ + XKB_MAP_COMPILE_NO_FLAGS = 0, /** Apparently you can't have empty enums. What a drag. */ XKB_MAP_COMPILE_PLACEHOLDER = 0 }; @@ -811,6 +826,46 @@ xkb_keymap_get_as_string(struct xkb_keymap *keymap, * @{ */ +/** + * Get the minimum keycode in the keymap. + * + * @sa xkb_keycode_t + * @memberof xkb_keymap + */ +xkb_keycode_t +xkb_keymap_min_keycode(struct xkb_keymap *keymap); + +/** + * Get the maximum keycode in the keymap. + * + * @sa xkb_keycode_t + * @memberof xkb_keymap + */ +xkb_keycode_t +xkb_keymap_max_keycode(struct xkb_keymap *keymap); + +/** + * The iterator used by xkb_keymap_key_for_each(). + * + * @sa xkb_keymap_key_for_each + * @memberof xkb_keymap + */ +typedef void +(*xkb_keymap_key_iter_t)(struct xkb_keymap *keymap, xkb_keycode_t key, + void *data); + +/** + * Run a specified function for every valid keycode in the keymap. If a + * keymap is sparse, this function may be called fewer than + * (max_keycode - min_keycode + 1) times. + * + * @sa xkb_keymap_min_keycode() xkb_keymap_max_keycode() xkb_keycode_t + * @memberof xkb_keymap + */ +void +xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter, + void *data); + /** * Get the number of modifiers in the keymap. * @@ -1001,9 +1056,9 @@ xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t key); */ /** - * Create a new keyboard state object for a keymap. + * Create a new keyboard state object. * - * @param keymap The keymap for which to create the state. + * @param keymap The keymap which the state will use. * * @returns A new keyboard state object, or NULL on failure. * @@ -1033,10 +1088,10 @@ void xkb_state_unref(struct xkb_state *state); /** - * Get the keymap from which a keyboard state object was created. + * Get the keymap which a keyboard state object is using. * - * @returns The keymap which was used in xkb_state_new() to create this - * state object. + * @returns The keymap which was passed to xkb_state_new() when creating + * this state object. * * This function does not take a new reference on the keymap; you must * explicitly reference it yourself if you plan to use it beyond the @@ -1070,7 +1125,8 @@ enum xkb_state_component { * lock has been pressed again. */ XKB_STATE_MODS_LOCKED = (1 << 2), /** Effective modifiers, i.e. currently active and affect key - * processing (derived from the other state components). */ + * processing (derived from the other state components). + * Use this unless you explictly care how the state came about. */ XKB_STATE_MODS_EFFECTIVE = (1 << 3), /** Depressed layout, i.e. a key is physically holding it. */ XKB_STATE_LAYOUT_DEPRESSED = (1 << 4), @@ -1081,7 +1137,8 @@ enum xkb_state_component { * has been pressed again. */ XKB_STATE_LAYOUT_LOCKED = (1 << 6), /** Effective layout, i.e. currently active and affects key processing - * (derived from the other state components). */ + * (derived from the other state components). + * Use this unless you explictly care how the state came about. */ XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7), /** LEDs (derived from the other state components). */ XKB_STATE_LEDS = (1 << 8) @@ -1091,15 +1148,64 @@ enum xkb_state_component { * Update the keyboard state to reflect a given key being pressed or * released. * + * This entry point is intended for programs which track the keyboard state + * explictly (like an evdev client). If the state is serialized to you by + * a master process (like a Wayland compositor) using functions like + * xkb_state_serialize_mods(), you should use xkb_state_update_mask() instead. + * The two functins should not generally be used together. + * + * A series of calls to this function should be consistent; that is, a call + * with XKB_KEY_DOWN for a key should be matched by an XKB_KEY_UP; if a key + * is pressed twice, it should be released twice; etc. Otherwise (e.g. due + * to missed input events), situations like "stuck modifiers" may occur. + * * @returns A mask of state components that have changed as a result of * the update. If nothing in the state has changed, returns 0. * * @memberof xkb_state + * + * @sa xkb_state_update_mask() */ enum xkb_state_component xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key, enum xkb_key_direction direction); +/** + * Update a keyboard state from a set of explicit masks. + * + * This entry point is intended for window systems and the like, where a + * master process holds an xkb_state, then serializes it over a wire + * protocol, and clients then use the serialization to feed in to their own + * xkb_state. + * + * All parameters must always be passed, or the resulting state may be + * incoherent. + * + * The serialization is lossy and will not survive round trips; it must only + * be used to feed slave state objects, and must not be used to update the + * master state. + * + * If you do not fit the description above, you should use + * xkb_state_update_key() instead. The two functions should not generally be + * used together. + * + * @returns A mask of state components that have changed as a result of + * the update. If nothing in the state has changed, returns 0. + * + * @memberof xkb_state + * + * @sa xkb_state_component + * @sa xkb_state_update_key + */ +enum xkb_state_component +xkb_state_update_mask(struct xkb_state *state, + xkb_mod_mask_t depressed_mods, + xkb_mod_mask_t latched_mods, + xkb_mod_mask_t locked_mods, + xkb_layout_index_t depressed_layout, + xkb_layout_index_t latched_layout, + xkb_layout_index_t locked_layout); + /** * Get the keysyms obtained from pressing a particular key in a given * keyboard state. @@ -1114,8 +1220,9 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key, * key in the given keyboard state. * * As an extension to XKB, this function can return more than one keysym. - * If you do not want to handle this case, you can use - * xkb_state_key_get_one_sym(). + * If you do not want to handle this case, you should use + * xkb_state_key_get_one_sym(), which additionally performs transformations + * which are specific to the one-keysym case. * * @returns The number of keysyms in the syms_out array. If no keysyms * are produced by the key in the given keyboard state, returns 0 and sets @@ -1131,9 +1238,10 @@ xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t key, * Get the single keysym obtained from pressing a particular key in a * given keyboard state. * - * This function is similar to xkb_state_key_get_syms(), but with a - * simplified interface for users which cannot or do not want to handle - * the case where multiple keysyms are returned. + * This function is similar to xkb_state_key_get_syms(), but intended + * for users which cannot or do not want to handle the case where + * multiple keysyms are returned (in which case this function is + * preferred). * * @returns The keysym. If the key does not have exactly one keysym, * returns XKB_KEY_NoSymbol @@ -1203,39 +1311,6 @@ enum xkb_state_match { XKB_STATE_MATCH_NON_EXCLUSIVE = (1 << 16) }; -/** - * Update a keyboard state from a set of explicit masks. - * - * This entry point is really only for window systems and the like, where a - * master process holds an xkb_state, then serializes it over a wire - * protocol, and clients then use the serialization to feed in to their own - * xkb_state. - * - * All parameters must always be passed, or the resulting state may be - * incoherent. - * - * The serialization is lossy and will not survive round trips; it must only - * be used to feed slave state objects, and must not be used to update the - * master state. - * - * Please do not use this unless you fit the description above. - * - * @returns A mask of state components that have changed as a result of - * the update. If nothing in the state has changed, returns 0. - * - * @memberof xkb_state - * - * @sa xkb_state_component - */ -enum xkb_state_component -xkb_state_update_mask(struct xkb_state *state, - xkb_mod_mask_t depressed_mods, - xkb_mod_mask_t latched_mods, - xkb_mod_mask_t locked_mods, - xkb_layout_index_t depressed_layout, - xkb_layout_index_t latched_layout, - xkb_layout_index_t locked_layout); - /** * The counterpart to xkb_state_update_mask for modifiers, to be used on * the server side of serialization. @@ -1336,11 +1411,11 @@ xkb_state_mod_index_is_active(struct xkb_state *state, xkb_mod_index_t idx, * given modifiers. * @param match The manner by which to match the state against the * given modifiers. - * @param ... The set of of modifier indexes to test, terminated by a + * @param ... The set of of modifier indices to test, terminated by a * XKB_MOD_INVALID argument (sentinel). * * @returns 1 if the modifiers are active, 0 if they are not. If any of - * the modifier indexes are invalid in the keymap, returns -1. + * the modifier indices are invalid in the keymap, returns -1. * * @memberof xkb_state */ diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon_workaround.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon_workaround.h deleted file mode 100644 index 58ce143978..0000000000 --- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon_workaround.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the plugins 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef XKBCOMMON_WORKAROUND_H -#define XKBCOMMON_WORKAROUND_H - -// Function utf32_to_utf8() is borrowed from the libxkbcommon library, -// file keysym-utf.c. The workaround should be removed once the fix from -// https://bugs.freedesktop.org/show_bug.cgi?id=56780 gets released. -static int utf32_to_utf8(uint32_t unichar, char *buffer) -{ - int count, shift, length; - uint8_t head; - - if (unichar <= 0x007f) { - buffer[0] = unichar; - buffer[1] = '\0'; - return 2; - } - else if (unichar <= 0x07FF) { - length = 2; - head = 0xc0; - } - else if (unichar <= 0xffff) { - length = 3; - head = 0xe0; - } - else if (unichar <= 0x1fffff) { - length = 4; - head = 0xf0; - } - else if (unichar <= 0x3ffffff) { - length = 5; - head = 0xf8; - } - else { - length = 6; - head = 0xfc; - } - - for (count = length - 1, shift = 0; count > 0; count--, shift += 6) - buffer[count] = 0x80 | ((unichar >> shift) & 0x3f); - - buffer[0] = head | ((unichar >> shift) & 0x3f); - buffer[length] = '\0'; - - return length + 1; -} - -static bool needWorkaround(uint32_t sym) -{ - /* patch encoding botch */ - if (sym == XKB_KEY_KP_Space) - return true; - - /* special keysyms */ - if ((sym >= XKB_KEY_BackSpace && sym <= XKB_KEY_Clear) || - (sym >= XKB_KEY_KP_Multiply && sym <= XKB_KEY_KP_9) || - sym == XKB_KEY_Return || sym == XKB_KEY_Escape || - sym == XKB_KEY_Delete || sym == XKB_KEY_KP_Tab || - sym == XKB_KEY_KP_Enter || sym == XKB_KEY_KP_Equal) - return true; - - return false; -} - -#endif // XKBCOMMON_WORKAROUND_H diff --git a/src/plugins/platforminputcontexts/compose/compose.pro b/src/plugins/platforminputcontexts/compose/compose.pro index 546a0a2af7..7182c458fc 100644 --- a/src/plugins/platforminputcontexts/compose/compose.pro +++ b/src/plugins/platforminputcontexts/compose/compose.pro @@ -6,8 +6,6 @@ load(qt_plugin) QT += gui-private -LIBS += $$QMAKE_LIBS_XKBCOMMON -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"' SOURCES += $$PWD/main.cpp \ @@ -19,14 +17,12 @@ HEADERS += $$PWD/qcomposeplatforminputcontext.h \ # libxkbcommon contains(QT_CONFIG, xkbcommon-qt): { + # dont't need x11 dependency for compose key plugin + QT_CONFIG -= use-xkbcommon-x11support include(../../../3rdparty/xkbcommon.pri) } else { LIBS += $$QMAKE_LIBS_XKBCOMMON QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON - equals(QMAKE_VERSION_XKBCOMMON, "0.2.0") { - DEFINES += XKBCOMMON_0_2_0 - INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/ - } } OTHER_FILES += $$PWD/compose.json diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index ca61b0e495..8bbb490022 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -51,10 +51,6 @@ #include -#ifdef XKBCOMMON_0_2_0 -#include -#endif - #include // LC_CTYPE #include // strchr, strncmp, etc. #include // strncasecmp @@ -326,23 +322,7 @@ ushort TableGenerator::keysymToUtf8(quint32 sym) QByteArray chars; int bytes; chars.resize(8); - -#ifdef XKBCOMMON_0_2_0 - if (needWorkaround(sym)) { - quint32 codepoint; - if (sym == XKB_KEY_KP_Space) - codepoint = XKB_KEY_space & 0x7f; - else - codepoint = sym & 0x7f; - - bytes = utf32_to_utf8(codepoint, chars.data()); - } else { - bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size()); - } -#else bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size()); -#endif - if (bytes == -1) qWarning("TableGenerator::keysymToUtf8 - buffer too small"); diff --git a/src/plugins/platforminputcontexts/platforminputcontexts.pro b/src/plugins/platforminputcontexts/platforminputcontexts.pro index 60b66bfb35..faea54b874 100644 --- a/src/plugins/platforminputcontexts/platforminputcontexts.pro +++ b/src/plugins/platforminputcontexts/platforminputcontexts.pro @@ -4,7 +4,6 @@ qtHaveModule(dbus) { !mac:!win32:SUBDIRS += ibus } -unix:!macx:!contains(DEFINES, QT_NO_XKBCOMMON): { - SUBDIRS += compose -} +contains(QT_CONFIG, xcb-plugin): SUBDIRS += compose + diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 966090dbd5..0a52640c9a 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -53,10 +53,6 @@ #include #include -#ifdef XKBCOMMON_0_2_0 -#include -#endif - #ifndef XK_ISO_Left_Tab #define XK_ISO_Left_Tab 0xFE20 #endif @@ -1398,23 +1394,7 @@ QString QXcbKeyboard::keysymToUnicode(xcb_keysym_t sym) const QByteArray chars; int bytes; chars.resize(7); - -#ifdef XKBCOMMON_0_2_0 - if (needWorkaround(sym)) { - quint32 codepoint; - if (sym == XKB_KEY_KP_Space) - codepoint = XKB_KEY_space & 0x7f; - else - codepoint = sym & 0x7f; - - bytes = utf32_to_utf8(codepoint, chars.data()); - } else { - bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size()); - } -#else bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size()); -#endif - if (bytes == -1) qWarning("QXcbKeyboard::handleKeyEvent - buffer too small"); chars.resize(bytes-1); diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro index bfbec91e3c..e19bb921e1 100644 --- a/src/plugins/platforms/xcb/xcb-plugin.pro +++ b/src/plugins/platforms/xcb/xcb-plugin.pro @@ -131,12 +131,9 @@ contains(QT_CONFIG, xcb-qt) { # libxkbcommon contains(QT_CONFIG, xkbcommon-qt): { + QT_CONFIG += use-xkbcommon-x11support include(../../../3rdparty/xkbcommon.pri) } else { LIBS += $$QMAKE_LIBS_XKBCOMMON QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON - equals(QMAKE_VERSION_XKBCOMMON, "0.2.0") { - DEFINES += XKBCOMMON_0_2_0 - INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/ - } } -- cgit v1.2.3 From b66950b342417d38b2f2992053b58ef59a84400b Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 14 Mar 2014 12:21:25 +0100 Subject: Fix typos in QRegExp documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I80bce716ac1c161fd87291ecdbf21eb8f3f25e5a Reviewed-by: André Hartmann Reviewed-by: Oswald Buddenhagen --- src/corelib/tools/qregexp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index d2b5adc974..cadf2da019 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -133,8 +133,8 @@ int qFindString(const QChar *haystack, int haystackLen, int from, or \b{5}. An expression can also be a set of characters enclosed in square brackets. \b{[ABCD]} will match an \b{A} or a \b{B} or a \b{C} or a \b{D}. We can write this same - expression as \b{[A-D]}, and an experession to match any - captital letter in the English alphabet is written as + expression as \b{[A-D]}, and an expression to match any + capital letter in the English alphabet is written as \b{[A-Z]}. A quantifier specifies the number of occurrences of an expression -- cgit v1.2.3 From c02cc25e833c7604c853661a41b5891e702efed0 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 18 Mar 2014 16:34:15 +0100 Subject: QMenu: Sloppy menu selection should allow hovering separators Setting the current action to 0 clears the sloppy region and closes the submenu if we hover a separator on the way to the submenu popup. Now, we choose not to while the sloppy delay timer is running. Task-number: QTBUG-20094 Change-Id: I9d1b1358fe64c259dc47f35db8fc8f2b19a73153 Reviewed-by: J-P Nurmi --- src/widgets/widgets/qmenu.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 6ad9c4073c..82de68eb4f 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2887,6 +2887,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) QAction *action = d->actionAt(e->pos()); if (!action || action->isSeparator()) { if (d->hasHadMouse + && d->sloppyDelayTimer == 0 // Keep things as they are while we're moving to the submenu && (!d->currentAction || (action && action->isSeparator()) || !(d->currentAction->menu() && d->currentAction->menu()->isVisible()))) d->setCurrentAction(0); -- cgit v1.2.3 From f5224bd4d1429858cf30052f8c0dd2608e186536 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 13 Mar 2014 07:38:47 +0100 Subject: QMenuPrivate: Make sloppyDelayTimer non-static Keeping the timer static would trigger warnings when enabling SH_Menu_SloppySubMenus in QCommonStyle in a forthcoming patch. This would happen if we opened a second level submenu quickly enough and get the mouse event handler to reset the timer its parent menu started. Change-Id: Ia768603b40b219f87138c60a595c65ef408761ae Reviewed-by: Marc Mutz --- src/widgets/widgets/qmenu.cpp | 17 ++++++++--------- src/widgets/widgets/qmenu_p.h | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 82de68eb4f..eb93e461c0 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -75,7 +75,6 @@ QT_BEGIN_NAMESPACE QMenu *QMenuPrivate::mouseDown = 0; -int QMenuPrivate::sloppyDelayTimer = 0; /* QMenu code */ // internal class used for the torn off popup @@ -2897,13 +2896,13 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) } if (d->sloppyRegion.contains(e->pos())) { // If the timer is already running then don't start a new one unless the action is the same - if (d->sloppyAction != action && QMenuPrivate::sloppyDelayTimer != 0) { - killTimer(QMenuPrivate::sloppyDelayTimer); - QMenuPrivate::sloppyDelayTimer = 0; + if (d->sloppyAction != action && d->sloppyDelayTimer != 0) { + killTimer(d->sloppyDelayTimer); + d->sloppyDelayTimer = 0; } - if (QMenuPrivate::sloppyDelayTimer == 0) { + if (d->sloppyDelayTimer == 0) { d->sloppyAction = action; - QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this) * 6); + d->sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this) * 6); } } else if (action != d->currentAction) { d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)); @@ -2945,9 +2944,9 @@ QMenu::timerEvent(QTimerEvent *e) } else if(d->menuDelayTimer.timerId() == e->timerId()) { d->menuDelayTimer.stop(); internalDelayedPopup(); - } else if(QMenuPrivate::sloppyDelayTimer == e->timerId()) { - killTimer(QMenuPrivate::sloppyDelayTimer); - QMenuPrivate::sloppyDelayTimer = 0; + } else if (d->sloppyDelayTimer == e->timerId()) { + killTimer(d->sloppyDelayTimer); + d->sloppyDelayTimer = 0; internalSetSloppyAction(); } else if(d->searchBufferTimer.timerId() == e->timerId()) { d->searchBuffer.clear(); diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index afd34a5c47..9d9851af64 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -92,7 +92,7 @@ public: cancelAction(0), #endif scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0), - hasCheckableItems(0), sloppyAction(0), doChildEffects(false), platformMenu(0) + hasCheckableItems(0), sloppyDelayTimer(0), sloppyAction(0), doChildEffects(false), platformMenu(0) #if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR) ,wce_menu(0) @@ -204,7 +204,7 @@ public: mutable bool hasCheckableItems; //sloppy selection - static int sloppyDelayTimer; + int sloppyDelayTimer; mutable QAction *sloppyAction; QRegion sloppyRegion; -- cgit v1.2.3 From aae382ab3b2c47946efc10f269fad77d8244b3f4 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 13 Mar 2014 08:40:04 +0100 Subject: QMenu: Enable sloppy submenu mouse navigation Since we're in the 21st century, we set QCommonStyle to return true to the SH_Menu_SloppySubMenus style hint. This unlocks all the logic already available in QMenu. Task-number: QTBUG-20094 [ChangeLog][QtWidgets][QMenu] Enable sloppy submenu mouse navigation Change-Id: I134c87e348d98d1f46055e0bfef2b4a4a3d2993a Reviewed-by: Shawn Rutledge Reviewed-by: Jens Bache-Wiig Reviewed-by: Marc Mutz --- src/widgets/styles/qcommonstyle.cpp | 4 ++++ src/widgets/styles/qmacstyle_mac.mm | 3 --- src/widgets/styles/qstyle.cpp | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 9c2163ac8f..2be0cdb9b6 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -4896,6 +4896,10 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget ret = 256; break; + case SH_Menu_SloppySubMenus: + ret = true; + break; + case SH_ProgressDialog_TextLabelAlignment: ret = Qt::AlignCenter; break; diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 53568f3c53..d4b937ec03 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -2532,9 +2532,6 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w ret = QDialogButtons::Reject; break; */ - case SH_Menu_SloppySubMenus: - ret = true; - break; case SH_GroupBox_TextLabelVerticalAlignment: ret = Qt::AlignTop; break; diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 7568ba4e6e..d244c10316 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -1706,8 +1706,10 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SH_Menu_Scrollable Whether popup menus must support scrolling. - \value SH_Menu_SloppySubMenus Whether popupmenu's must support - sloppy submenu; as implemented on Mac OS. + \value SH_Menu_SloppySubMenus Whether popup menus must support + the user moving the mouse cursor to a submenu while crossing + other items of the menu. This is supported on most modern + desktop platforms. \value SH_ScrollView_FrameOnlyAroundContents Whether scrollviews draw their frame only around contents (like Motif), or around -- cgit v1.2.3 From aea988a3d96a9f9951c6e4c4e0ff8abca726c2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 19 Mar 2014 13:25:20 +0100 Subject: Remove 'register' storage class specifier in armv6 atomics It is deprecated, and produces warnings on recent Clang versions. Change-Id: I83181dd12c06a600a2f0eafbd83fe6111cf7752c Reviewed-by: Thiago Macieira --- src/corelib/arch/qatomic_armv6.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 31a06541ed..3fd07e0813 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -171,8 +171,8 @@ bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa template<> template inline bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { - register T tempValue; - register int result; + T tempValue; + int result; asm volatile("0:\n" "ldrex %[tempValue], [%[_q_value]]\n" "eors %[result], %[tempValue], %[expectedValue]\n" @@ -352,8 +352,8 @@ bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa template<> template inline bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { - register T tempValue; - register T result; + T tempValue; + T result; asm volatile("0:\n" "ldrexb %[tempValue], [%[_q_value]]\n" "eors %[result], %[tempValue], %[expectedValue]\n" @@ -474,8 +474,8 @@ bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa template<> template inline bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { - register T tempValue; - register T result; + T tempValue; + T result; asm volatile("0:\n" "ldrexh %[tempValue], [%[_q_value]]\n" "eors %[result], %[tempValue], %[expectedValue]\n" @@ -608,8 +608,8 @@ bool QBasicAtomicOps<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa template<> template inline bool QBasicAtomicOps<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { - register T tempValue; - register T result; + T tempValue; + T result; asm volatile("0:\n" "ldrexd %[tempValue], %H[tempValue], [%[_q_value]]\n" "eor %[result], %[tempValue], %[expectedValue]\n" -- cgit v1.2.3 From 379238496d0bf339a717a311e91949deb2e45485 Mon Sep 17 00:00:00 2001 From: Eduard Veleba Date: Wed, 19 Mar 2014 13:53:57 +0100 Subject: Workaround for misbehaving [UIScreen screens] in iOS 7.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On iOS 7.1 [UIScreen screens] sometimes returns empty NSArray which is against documentation and causes immediate application crash. This workaround uses [UIScreen mainScreen] in case [UIScreen screens] returns empty NSArray. Task-number: QTBUG-37601 Change-Id: I9b341b9ca788b5fc81804489d2e0a3af84207168 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosscreen.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 96410952f9..5331d05ae9 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -120,7 +120,9 @@ static QString deviceModelIdentifier() QIOSScreen::QIOSScreen(unsigned int screenIndex) : QPlatformScreen() - , m_uiScreen([[UIScreen screens] objectAtIndex:qMin(NSUInteger(screenIndex), [[UIScreen screens] count] - 1)]) + , m_uiScreen([[UIScreen screens] count] > screenIndex + ? [[UIScreen screens] objectAtIndex:screenIndex] + : [UIScreen mainScreen]) , m_orientationListener(0) { QString deviceIdentifier = deviceModelIdentifier(); -- cgit v1.2.3 From 3ff15f1e987e59b5c35224d7f2230905c4a5f3d0 Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Tue, 11 Mar 2014 14:12:46 +0100 Subject: QOpenGLContext: Use color depth information from QSurfaceFormat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a new QOpenGLContext is requested, the color depth information is now also taken into account on OS X and WGL. Task-number: QTBUG-37411 Change-Id: I69d04989a20de3ace041b009fbbdc03fa02cfdf8 Reviewed-by: Laszlo Agocs Reviewed-by: Morten Johan Sørvig Reviewed-by: Friedemann Kleint --- src/gui/kernel/qsurfaceformat.cpp | 12 ++++++++++++ src/platformsupport/cglconvenience/cglconvenience.mm | 8 ++++++++ src/plugins/platforms/windows/qwindowsglcontext.cpp | 7 ++++++- 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index 2b6cb2d949..23c0e59779 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -522,6 +522,10 @@ int QSurfaceFormat::alphaBufferSize() const /*! Set the desired \a size in bits of the red channel of the color buffer. + + \note On Mac OSX, be sure to set the buffer size of all color channels, + otherwise this setting will have no effect. If one of the buffer sizes is not set, + the current bit-depth of the screen is used. */ void QSurfaceFormat::setRedBufferSize(int size) { @@ -533,6 +537,10 @@ void QSurfaceFormat::setRedBufferSize(int size) /*! Set the desired \a size in bits of the green channel of the color buffer. + + \note On Mac OSX, be sure to set the buffer size of all color channels, + otherwise this setting will have no effect. If one of the buffer sizes is not set, + the current bit-depth of the screen is used. */ void QSurfaceFormat::setGreenBufferSize(int size) { @@ -544,6 +552,10 @@ void QSurfaceFormat::setGreenBufferSize(int size) /*! Set the desired \a size in bits of the blue channel of the color buffer. + + \note On Mac OSX, be sure to set the buffer size of all color channels, + otherwise this setting will have no effect. If one of the buffer sizes is not set, + the current bit-depth of the screen is used. */ void QSurfaceFormat::setBlueBufferSize(int size) { diff --git a/src/platformsupport/cglconvenience/cglconvenience.mm b/src/platformsupport/cglconvenience/cglconvenience.mm index 7379919588..d0b0de8ae8 100644 --- a/src/platformsupport/cglconvenience/cglconvenience.mm +++ b/src/platformsupport/cglconvenience/cglconvenience.mm @@ -114,6 +114,14 @@ void *qcgl_createNSOpenGLPixelFormat(const QSurfaceFormat &format) attrs << NSOpenGLPFAStencilSize << format.stencilBufferSize(); if (format.alphaBufferSize() > 0) attrs << NSOpenGLPFAAlphaSize << format.alphaBufferSize(); + if ((format.redBufferSize() > 0) && + (format.greenBufferSize() > 0) && + (format.blueBufferSize() > 0)) { + const int colorSize = format.redBufferSize() + + format.greenBufferSize() + + format.blueBufferSize(); + attrs << NSOpenGLPFAColorSize << colorSize << NSOpenGLPFAMinimumPolicy; + } if (format.samples() > 0) { attrs << NSOpenGLPFAMultisample diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index c45c34ae4d..e7e4028079 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -387,7 +387,12 @@ static int choosePixelFormat(HDC hdc, iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB; iAttributes[i++] = TRUE; iAttributes[i++] = WGL_COLOR_BITS_ARB; - iAttributes[i++] = 24; + + iAttributes[i++] = (format.redBufferSize() > 0) + && (format.greenBufferSize() > 0) + && (format.blueBufferSize() > 0) ? + format.redBufferSize() + format.greenBufferSize() + format.blueBufferSize() : + 24; switch (format.swapBehavior()) { case QSurfaceFormat::SingleBuffer: iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; -- cgit v1.2.3 From 83b3924cc38df57ff0be3114417faec7f97b021c Mon Sep 17 00:00:00 2001 From: aavit Date: Tue, 4 Mar 2014 14:56:04 +0100 Subject: Fixes: style runtime warnings when painting too small widgets Trying to create a 0-size cache image would lead to trying to paint to a null image, giving runtime warnings. Task-number: QTBUG-37035 Change-Id: I0a7fdb19cc7548dea2770d6be4eb283f6b898ada Reviewed-by: Jens Bache-Wiig --- src/widgets/styles/qstyle_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h index 70221f6d8f..9f25492173 100644 --- a/src/widgets/styles/qstyle_p.h +++ b/src/widgets/styles/qstyle_p.h @@ -96,8 +96,8 @@ inline QPixmap styleCachePixmap(const QSize &size) QPainter *p = painter; \ QString unique = QStyleHelper::uniqueName((a), option, option->rect.size()); \ int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \ - bool doPixmapCache = (txType <= QTransform::TxTranslate) \ - || (painter->deviceTransform().type() == QTransform::TxScale); \ + bool doPixmapCache = (!option->rect.isEmpty()) \ + && ((txType <= QTransform::TxTranslate) || (painter->deviceTransform().type() == QTransform::TxScale)); \ if (doPixmapCache && QPixmapCache::find(unique, internalPixmapCache)) { \ painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \ } else { \ -- cgit v1.2.3 From 0e69c942228d4a30bf1d490ded9ee9d2bd1f0b6b Mon Sep 17 00:00:00 2001 From: aavit Date: Mon, 17 Mar 2014 15:00:22 +0100 Subject: Fix compile for embedded Android Cannot use JNI to query for standard paths Change-Id: I1596106fd4d5e532d3ac1cd6dbfce3fb9fe1db5a Reviewed-by: Christian Stromme --- src/corelib/io/io.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 989e4644c7..f651860e08 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -148,7 +148,7 @@ win32 { } } else:blackberry { SOURCES += io/qstandardpaths_blackberry.cpp - } else:android { + } else:android:!android-no-sdk { SOURCES += io/qstandardpaths_android.cpp } else { SOURCES += io/qstandardpaths_unix.cpp -- cgit v1.2.3 From 1cc421eb250a2fabe55133155a5c5ab8a0e5dd31 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 18 Mar 2014 15:05:48 +0100 Subject: Use parent cursor for QLineEdit's clear button when not shown. Task-number: QTBUG-37548 Change-Id: I8a4eb52f9a5a9551e53dab100f2337cf201d7401 Reviewed-by: Giuseppe D'Angelo --- src/widgets/widgets/qlineedit_p.cpp | 12 +++++++++--- src/widgets/widgets/qlineedit_p.h | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 9ff77c87de..10689b2fc3 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -309,9 +309,7 @@ QLineEditIconButton::QLineEditIconButton(QWidget *parent) : QToolButton(parent) , m_opacity(0) { -#ifndef QT_NO_CURSOR - setCursor(Qt::ArrowCursor); -#endif + updateCursor(); setFocusPolicy(Qt::NoFocus); } @@ -342,11 +340,19 @@ void QLineEditIconButton::setOpacity(qreal value) void QLineEditIconButton::startOpacityAnimation(qreal endValue) { QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity")); + connect(animation, &QAbstractAnimation::finished, this, &QLineEditIconButton::updateCursor); animation->setDuration(160); animation->setEndValue(endValue); animation->start(QAbstractAnimation::DeleteWhenStopped); } +void QLineEditIconButton::updateCursor() +{ +#ifndef QT_NO_CURSOR + setCursor(qFuzzyCompare(m_opacity, 1.0) || !parentWidget() ? QCursor(Qt::ArrowCursor) : parentWidget()->cursor()); +#endif +} + void QLineEditPrivate::_q_textChanged(const QString &text) { if (hasSideWidgets()) { diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index aa5b57a920..db8edee005 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -89,6 +89,9 @@ public: protected: void paintEvent(QPaintEvent *event); +private slots: + void updateCursor(); + private: void startOpacityAnimation(qreal endValue); -- cgit v1.2.3 From a466743f744e41bfdf0f7333b452a02ecc31dbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 17 Mar 2014 13:26:26 +0100 Subject: Cocoa: Enable QQuickWidget on Mac OS X. Change-Id: I0635bf0bfcd49c20987a81c6f8895fc3343fbd20 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/cocoa/qcocoabackingstore.h | 1 + src/plugins/platforms/cocoa/qcocoabackingstore.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoaglcontext.mm | 2 +- src/plugins/platforms/cocoa/qcocoaintegration.mm | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index ce8ebbc79e..a33373c4c1 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -59,6 +59,7 @@ public: QPaintDevice *paintDevice(); void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset); + QImage toImage() const Q_DECL_OVERRIDE; void resize (const QSize &size, const QRegion &); bool scroll(const QRegion &area, int dx, int dy); CGImageRef getBackingStoreCGImage(); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 2222b51a42..d76645c668 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -96,6 +96,11 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion ®ion, const QPoint } } +QImage QCocoaBackingStore::toImage() const +{ + return m_qImage; +} + void QCocoaBackingStore::resize(const QSize &size, const QRegion &) { m_requestedSize = size; diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 9b4d8fd96f..3f61bd81ee 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -194,7 +194,7 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) { - Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Q_ASSERT(surface->surface()->supportsOpenGL()); QCocoaAutoReleasePool pool; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index d612c7ff28..65a9f87e2d 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -375,6 +375,7 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons case WindowMasks: case MultipleWindows: case ForeignWindows: + case RasterGLSurface: return true; default: return QPlatformIntegration::hasCapability(cap); -- cgit v1.2.3 From 669588484fe4ee4ab1fddf39887d684d563b7450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 18 Mar 2014 11:30:05 +0100 Subject: Cocoa: Close windows with QWSI::handleCloseEvent() Calling QWindow::close() directly bypasses some of the window close logic in the QWindow subclasses. Change-Id: I208db5600e6a756e25e207eaaf55dcfad255f406 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 327ca00ad6..f8411845dc 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -223,8 +223,9 @@ static void cleanupCocoaApplicationDelegate() // events while the event loop is still running. const QWindowList topLevels = QGuiApplication::topLevelWindows(); for (int i = 0; i < topLevels.size(); ++i) { - topLevels.at(i)->close(); + QWindowSystemInterface::handleCloseEvent(topLevels.at(i)); } + QWindowSystemInterface::flushWindowSystemEvents(); QGuiApplication::exit(0); startedQuit = false; -- cgit v1.2.3 From 07549de92bcb2e138c2f3c8d555092054a5359db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 18 Mar 2014 13:34:00 +0100 Subject: Delete the OpenGL context before the window. Fix a crash-on-exit on Mac, where deleting the context references the attached NSView. Change-Id: Iac38184dab7a406e4072452fd9a6b175e6968ade Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidget_qpa.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 88a08060c1..85ae55b8ac 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -959,6 +959,8 @@ void QWidgetPrivate::deleteTLSysExtra() #ifndef QT_NO_OPENGL if (textureChildSeen && extra->topextra->shareContext) extra->topextra->shareContext->doneCurrent(); + delete extra->topextra->shareContext; + extra->topextra->shareContext = 0; #endif //the toplevel might have a context with a "qglcontext associated with it. We need to @@ -972,10 +974,6 @@ void QWidgetPrivate::deleteTLSysExtra() delete extra->topextra->window; extra->topextra->window = 0; -#ifndef QT_NO_OPENGL - delete extra->topextra->shareContext; - extra->topextra->shareContext = 0; -#endif } } -- cgit v1.2.3 From 5e03c4d97f72f96a8fc97aa87f24c41a043048b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 18 Mar 2014 13:36:10 +0100 Subject: QOpenGLWidget retina support. Use device pixels where appropriate. Change-Id: Ia953e6da4034eecbfccf798701ec1b850eea9d5b Reviewed-by: Paul Olav Tvete --- src/gui/painting/qplatformbackingstore.cpp | 32 ++++++++++++++++++++++++++---- src/widgets/kernel/qopenglwidget.cpp | 2 +- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 4843e93858..add3624feb 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -186,6 +186,28 @@ void QPlatformTextureList::clear() */ #ifndef QT_NO_OPENGL + +static QRect deviceRect(const QRect &rect, QWindow *window) +{ + QRect deviceRect(rect.topLeft() * window->devicePixelRatio(), + rect.size() * window->devicePixelRatio()); + return deviceRect; +} + +static QRegion deviceRegion(const QRegion ®ion, QWindow *window) +{ + if (!(window->devicePixelRatio() > 1)) + return region; + + QVector rects; + foreach (QRect rect, region.rects()) + rects.append(deviceRect(rect, window)); + + QRegion deviceRegion; + deviceRegion.setRects(rects.constData(), rects.count()); + return deviceRegion; +} + /*! Flushes the given \a region from the specified \a window onto the screen, and composes it with the specified \a textures. @@ -205,7 +227,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i context->makeCurrent(window); QOpenGLFunctions *funcs = context->functions(); - funcs->glViewport(0, 0, window->width(), window->height()); + funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio()); if (!d_ptr->blitter) { d_ptr->blitter = new QOpenGLTextureBlitter; @@ -214,16 +236,18 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i d_ptr->blitter->bind(); - QRect windowRect(QPoint(), window->size()); + QRect windowRect(QPoint(), window->size() * window->devicePixelRatio()); + for (int i = 0; i < textures->count(); ++i) { GLuint textureId = textures->textureId(i); funcs->glBindTexture(GL_TEXTURE_2D, textureId); - QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), windowRect); + QRect targetRect = deviceRect(textures->geometry(i), window); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, windowRect); d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); } - GLuint textureId = toTexture(region); + GLuint textureId = toTexture(deviceRegion(region, window)); if (!textureId) return; diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index e05c03d952..66aacadb28 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -163,7 +163,7 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *) d->context.makeCurrent(d->surface()); delete d->fbo; // recreate when resized - d->fbo = new QOpenGLFramebufferObject(size()); + d->fbo = new QOpenGLFramebufferObject(size() * devicePixelRatio()); d->fbo->bind(); QOpenGLFunctions *funcs = d->context.functions(); funcs->glBindTexture(GL_TEXTURE_2D, d->fbo->texture()); -- cgit v1.2.3 From 5fe0c9e9b02669c8690d78b5305e1291d0f807bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 19 Mar 2014 10:11:32 +0100 Subject: Cocoa: Set surface resolution for all GL surfaces Change-Id: Ic54ad954a157ff777312361b7816b1752afbf75f Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/cocoa/qcocoawindow.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 957428d043..293d3093e3 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -392,7 +392,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) // problem, except if the appilcation wants to have a "custom" viewport. // (like the hellogl example) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 - && tlw->surfaceType() == QSurface::OpenGLSurface) { + && tlw->supportsOpenGL()) { BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); [m_contentView setWantsBestResolutionOpenGLSurface:enable]; -- cgit v1.2.3 From 53ee91fc8de377071939fa8d36423b6bee7e27a4 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 18 Mar 2014 15:59:03 +0100 Subject: Fix QAbstractScrollArea to respect transiency per scrollbar Do not query scrollarea's own style whether the scrollarea itself is a transient scrollbar, but query both scrollbar's style individually. Change-Id: I6397a29bc7b276a92c538cbb7fc0dd921595d093 Reviewed-by: Jens Bache-Wiig --- src/widgets/widgets/qabstractscrollarea.cpp | 56 ++++++++++++++++------------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index db4ff8a2b7..e1e933cdd8 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -329,19 +329,21 @@ void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on) void QAbstractScrollAreaPrivate::layoutChildren() { Q_Q(QAbstractScrollArea); - bool transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar ? vbar : hbar); - bool needh = (hbarpolicy != Qt::ScrollBarAlwaysOff) && ((hbarpolicy == Qt::ScrollBarAlwaysOn && !transient) - || ((hbarpolicy == Qt::ScrollBarAsNeeded || transient) + bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, hbar); + bool needh = (hbarpolicy != Qt::ScrollBarAlwaysOff) && ((hbarpolicy == Qt::ScrollBarAlwaysOn && !htransient) + || ((hbarpolicy == Qt::ScrollBarAsNeeded || htransient) && hbar->minimum() < hbar->maximum() && !hbar->sizeHint().isEmpty())); - bool needv = (vbarpolicy != Qt::ScrollBarAlwaysOff) && ((vbarpolicy == Qt::ScrollBarAlwaysOn && !transient) - || ((vbarpolicy == Qt::ScrollBarAsNeeded || transient) + bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar); + bool needv = (vbarpolicy != Qt::ScrollBarAlwaysOff) && ((vbarpolicy == Qt::ScrollBarAlwaysOn && !vtransient) + || ((vbarpolicy == Qt::ScrollBarAsNeeded || vtransient) && vbar->minimum() < vbar->maximum() && !vbar->sizeHint().isEmpty())); QStyleOption opt(0); opt.init(q); - const int scrollOverlap = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, - &opt, q); + + const int hscrollOverlap = hbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &opt, hbar); + const int vscrollOverlap = vbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &opt, vbar); #ifdef Q_WS_MAC QWidget * const window = q->window(); @@ -408,7 +410,7 @@ void QAbstractScrollAreaPrivate::layoutChildren() } #endif - QPoint cornerOffset((needv && scrollOverlap == 0) ? vsbExt : 0, (needh && scrollOverlap == 0) ? hsbExt : 0); + QPoint cornerOffset((needv && vscrollOverlap == 0) ? vsbExt : 0, (needh && hscrollOverlap == 0) ? hsbExt : 0); QRect controlsRect; QRect viewportRect; @@ -417,8 +419,8 @@ void QAbstractScrollAreaPrivate::layoutChildren() if ((frameStyle != QFrame::NoFrame) && q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, q)) { controlsRect = widgetRect; - const int extra = scrollOverlap + q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, q); - const QPoint cornerExtra(needv ? extra : 0, needh ? extra : 0); + const int spacing = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, q); + const QPoint cornerExtra(needv ? spacing + vscrollOverlap : 0, needh ? spacing + hscrollOverlap : 0); QRect frameRect = widgetRect; frameRect.adjust(0, 0, -cornerOffset.x() - cornerExtra.x(), -cornerOffset.y() - cornerExtra.y()); q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, frameRect)); @@ -436,7 +438,7 @@ void QAbstractScrollAreaPrivate::layoutChildren() // If we have a corner widget and are only showing one scroll bar, we need to move it // to make room for the corner widget. - if (hasCornerWidget && (needv || needh) && scrollOverlap == 0) + if (hasCornerWidget && ((needv && vscrollOverlap == 0) || (needh && hscrollOverlap == 0))) cornerOffset = extPoint; #ifdef Q_WS_MAC @@ -452,7 +454,7 @@ void QAbstractScrollAreaPrivate::layoutChildren() // Some styles paints the corner if both scorllbars are showing and there is // no corner widget. Also, on the Mac we paint if there is a native // (transparent) sizegrip in the area where a corner widget would be. - if ((needv && needh && hasCornerWidget == false && scrollOverlap == 0) + if ((needv && needh && hasCornerWidget == false && hscrollOverlap == 0 && vscrollOverlap == 0) || ((needv || needh) #ifdef Q_WS_MAC && hasMacSizeGrip @@ -474,7 +476,7 @@ void QAbstractScrollAreaPrivate::layoutChildren() // move the scrollbars away from top/left headers int vHeaderRight = 0; int hHeaderBottom = 0; - if (scrollOverlap > 0 && (needv || needh)) { + if ((vscrollOverlap > 0 && needv) || (hscrollOverlap > 0 && needh)) { const QList headers = q->findChildren(); if (headers.count() <= 2) { Q_FOREACH (const QHeaderView *header, headers) { @@ -493,20 +495,22 @@ void QAbstractScrollAreaPrivate::layoutChildren() if (hasMacReverseSizeGrip) horizontalScrollBarRect.adjust(vsbExt, 0, 0, 0); #endif + if (!hasCornerWidget && htransient) #ifdef Q_OS_MAC - if (!hasCornerWidget && QSysInfo::macVersion() >= QSysInfo::MV_10_8 && transient) - horizontalScrollBarRect.adjust(0, 0, cornerOffset.x(), 0); + if (QSysInfo::macVersion() >= QSysInfo::MV_10_8) #endif + horizontalScrollBarRect.adjust(0, 0, cornerOffset.x(), 0); scrollBarContainers[Qt::Horizontal]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, horizontalScrollBarRect)); scrollBarContainers[Qt::Horizontal]->raise(); } if (needv) { QRect verticalScrollBarRect (QPoint(cornerPoint.x(), controlsRect.top() + hHeaderBottom), QPoint(controlsRect.right(), cornerPoint.y() - 1)); + if (!hasCornerWidget && vtransient) #ifdef Q_OS_MAC - if (!hasCornerWidget && QSysInfo::macVersion() >= QSysInfo::MV_10_8 && transient) - verticalScrollBarRect.adjust(0, 0, 0, cornerOffset.y()); + if (QSysInfo::macVersion() >= QSysInfo::MV_10_8) #endif + verticalScrollBarRect.adjust(0, 0, 0, cornerOffset.y()); scrollBarContainers[Qt::Vertical]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, verticalScrollBarRect)); scrollBarContainers[Qt::Vertical]->raise(); } @@ -957,10 +961,12 @@ bool QAbstractScrollArea::eventFilter(QObject *o, QEvent *e) { Q_D(QAbstractScrollArea); if ((o == d->hbar || o == d->vbar) && (e->type() == QEvent::HoverEnter || e->type() == QEvent::HoverLeave)) { - Qt::ScrollBarPolicy policy = o == d->hbar ? d->vbarpolicy : d->hbarpolicy; - if (policy == Qt::ScrollBarAsNeeded || style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, d->vbar ? d->vbar : d->hbar)) { - QScrollBar *sibling = o == d->hbar ? d->vbar : d->hbar; - d->setScrollBarTransient(sibling, e->type() == QEvent::HoverLeave); + if (d->hbarpolicy == Qt::ScrollBarAsNeeded && d->vbarpolicy == Qt::ScrollBarAsNeeded) { + QScrollBar *sbar = static_cast(o); + QScrollBar *sibling = sbar == d->hbar ? d->vbar : d->hbar; + if (sbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, sbar) && + sibling->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, sibling)) + d->setScrollBarTransient(sibling, e->type() == QEvent::HoverLeave); } } return QFrame::eventFilter(o, e); @@ -1479,11 +1485,11 @@ bool QAbstractScrollAreaPrivate::canStartScrollingAt( const QPoint &startPos ) void QAbstractScrollAreaPrivate::flashScrollBars() { - Q_Q(QAbstractScrollArea); - bool transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar ? vbar : hbar); - if ((hbarpolicy != Qt::ScrollBarAlwaysOff) && (hbarpolicy == Qt::ScrollBarAsNeeded || transient)) + bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, hbar); + if ((hbarpolicy != Qt::ScrollBarAlwaysOff) && (hbarpolicy == Qt::ScrollBarAsNeeded || htransient)) hbar->d_func()->flash(); - if ((vbarpolicy != Qt::ScrollBarAlwaysOff) && (vbarpolicy == Qt::ScrollBarAsNeeded || transient)) + bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar); + if ((vbarpolicy != Qt::ScrollBarAlwaysOff) && (vbarpolicy == Qt::ScrollBarAsNeeded || vtransient)) vbar->d_func()->flash(); } -- cgit v1.2.3 From 84c8e4717c70f0f214f84a5c9430dcc024bf2e8b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 19 Mar 2014 09:55:05 +0100 Subject: Android: Re-enable threaded rendering In Qt 5.2.x, the platform plugin inherited from the EGLFS platform plugin, so calling the super class implementation of hasCapability() would return true for ThreadedOpenGL. Since this link was removed in Qt 5.3, we would return false for all devices, giving us a large performance regression. Task-number: QTBUG-37586 Change-Id: I27758649ee9c0921902787b93be943751c839eb8 Reviewed-by: Paul Olav Tvete Reviewed-by: BogDan Vatra Reviewed-by: Alessandro Portale Reviewed-by: Gunnar Sletta --- src/plugins/platforms/android/qandroidplatformintegration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 2cca974b41..9adefd5b2c 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -152,7 +152,8 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const case ThreadedOpenGL: if (needsWorkaround()) return false; - // fall through + else + return true; default: return QPlatformIntegration::hasCapability(cap); } -- cgit v1.2.3 From f84e72600e70a0e05b9f81db4b89d2451f5b93c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 17 Mar 2014 15:38:08 +0100 Subject: Android: Check for exception before calling NewGlobalRef(). Calling NewGlobalRef() throws an exception if it gets an invalid ref. If one of the jni object-calls throws an exception and the returned reference is invalid, the subsequent call to NewGlobalRef() will trigger the second exception and the process will be terminated. Change-Id: I50c622e695542373d5b2eebd911c882e8e0f6bf7 Reviewed-by: Yoann Lopes --- src/corelib/kernel/qjni.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index aaa75c0fb8..623662a628 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -1264,6 +1264,8 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); if (id) { res = env->CallObjectMethodV(d->m_jobject, id, args); + if (res && env->ExceptionCheck()) + res = 0; } QJNIObjectPrivate obj(res); @@ -1342,6 +1344,8 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *classNam jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticObjectMethodV(clazz, id, args); + if (res && env->ExceptionCheck()) + res = 0; } } @@ -1372,6 +1376,8 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticObjectMethodV(clazz, id, args); + if (res && env->ExceptionCheck()) + res = 0; } QJNIObjectPrivate obj(res); @@ -1685,8 +1691,11 @@ QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName, QJNIEnvironmentPrivate env; jobject res = 0; jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig); - if (id) + if (id) { res = env->GetObjectField(d->m_jobject, id); + if (res && env->ExceptionCheck()) + res = 0; + } QJNIObjectPrivate obj(res); env->DeleteLocalRef(res); @@ -1713,8 +1722,11 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz, QJNIEnvironmentPrivate env; jobject res = 0; jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true); - if (id) + if (id) { res = env->GetStaticObjectField(clazz, id); + if (res && env->ExceptionCheck()) + res = 0; + } QJNIObjectPrivate obj(res); env->DeleteLocalRef(res); -- cgit v1.2.3 From 1f6e461533f531a25bdb9cf60c1cafc125aa06ba Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Mon, 2 Dec 2013 14:01:59 +0100 Subject: Fix positional binding values order in QSqlQuery Adapt the stringification code, that is used to produce the keys for QSqlQuery::boundValues() return value, to keep the right order of the binding values. Task-number: QTBUG-12186 Change-Id: Ic11a455bfd9ffd1418b1b021ce5cf78cae9b4504 [ChangeLog][QtSql] Fixed the order of values with positional binding in a QSqlQuery Reviewed-by: Andy Shaw Reviewed-by: Mark Brand --- src/sql/kernel/qsqlresult.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 31b05ab9e9..6959dc39f7 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -64,15 +64,20 @@ QString QSqlResultPrivate::holderAt(int index) const // return a unique id for bound names QString QSqlResultPrivate::fieldSerial(int i) const { - ushort arr[] = { ':', 'f', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - ushort *ptr = &arr[1]; + ushort arr[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + ushort *end = &arr[(sizeof(arr)/sizeof(*arr))]; + ushort *ptr = end; while (i > 0) { - *(++ptr) = 'a' + i % 16; + *(--ptr) = 'a' + i % 16; i >>= 4; } - return QString(reinterpret_cast(arr), int(ptr - arr) + 1); + const int nb = end - ptr; + *(--ptr) = 'a' + nb; + *(--ptr) = ':'; + + return QString::fromUtf16(ptr, int(end - ptr)); } static bool qIsAlnum(QChar ch) -- cgit v1.2.3 From 9508ea4c501c42b9c39dd6026a543d5766836097 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 19 Mar 2014 15:48:08 +0100 Subject: Correct QPainter::setPen() documentation. The default pen width is 1 as of Qt 5. Task-number: QTBUG-37277 Change-Id: I5b7b9c2019bd0e812384e67812b7bcfde37d0b53 Reviewed-by: Gunnar Sletta --- src/gui/painting/qpainter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index e35cdd370e..fe5fc051df 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -3828,7 +3828,7 @@ Qt::BGMode QPainter::backgroundMode() const /*! \overload - Sets the painter's pen to have style Qt::SolidLine, width 0 and the + Sets the painter's pen to have style Qt::SolidLine, width 1 and the specified \a color. */ -- cgit v1.2.3 From f5b552b5900d3bed72ace43c22f35c09b499bbdf Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 19 Mar 2014 16:00:40 +0100 Subject: Return false on context creation failure Make QOpenGLContext::create() return false when the native context could not be initialized. This way the return value and isValid() become equivalent. Relying on on having a non-NULL platform context is not enough, many platforms will return a new instance even if the underlying platform code failed to create a native context. To ensure that a platform context is really usable, isValid() has to be checked too. Change-Id: I6b4e9fdb24347ad52fbd6edbb8d144d51e16c301 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qopenglcontext.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 7ccdd7395b..5087e33b47 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -247,8 +247,8 @@ QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex; To set up a context, set its screen and format such that they match those of the surface or surfaces with which the context is meant to be used, if necessary make it share resources with other contexts with - setShareContext(), and finally call create(). Use isValid() to check if the - context was successfully initialized. + setShareContext(), and finally call create(). Use the return value or isValid() + to check if the context was successfully initialized. A context can be made current against a given surface by calling makeCurrent(). When OpenGL rendering is done, call swapBuffers() to swap @@ -491,7 +491,7 @@ bool QOpenGLContext::create() d->shareContext = 0; d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QOpenGLContextGroup; d->shareGroup->d_func()->addContext(this); - return d->platformGLContext; + return isValid(); } /*! -- cgit v1.2.3 From 8c91c9912f556897db4f05be1acc335ef3a5d1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 19 Mar 2014 11:26:30 +0100 Subject: Avoid QImage copy in toTexture() Desktop OpenGL has GL_UNPACK_ROW_LENGTH which we can use use to specify the image row stride. This removes the need to call QImage::copy(). On a retina MacbBok pro this reduces toTexture's share of the total run time by 1-4%. (on tests/manual/ qopenglwidget/openglwidget) Change-Id: Ia7f49d5c4ffcc347a495701bbaca6aecc2dc3433 Reviewed-by: Paul Olav Tvete Reviewed-by: Laszlo Agocs --- src/gui/painting/qplatformbackingstore.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index add3624feb..710d84e3aa 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -330,6 +330,13 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion) const funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); QRect imageRect = image.rect(); QRect rect = dirtyRegion.boundingRect() & imageRect; + +#ifndef QT_OPENGL_ES_2 + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width()); + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + image.constScanLine(rect.y()) + rect.x() * 4); + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +#else // if the rect is wide enough it's cheaper to just // extend it instead of doing an image copy if (rect.width() >= imageRect.width() / 2) { @@ -347,6 +354,7 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion) const funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.copy(rect).constBits()); } +#endif } return d_ptr->textureId; -- cgit v1.2.3 From 7c824bdb51115436b3cf17ccd463ed17459e6907 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 19 Mar 2014 13:34:13 +0100 Subject: Update year in About Qt dialog Change-Id: Ibbca2026c21394b68309cafe71e6d46065785f9b Reviewed-by: Jani Heikkinen Reviewed-by: Sergio Ahumada --- src/widgets/dialogs/qmessagebox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 207fe3d527..dcddc693c8 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1912,7 +1912,7 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title) "to comply with the terms of the GNU GPL version 3.0.

    " "

    Please see qt.digia.com/Product/Licensing " "for an overview of Qt licensing.

    " - "

    Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies) and other " + "

    Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies) and other " "contributors.

    " "

    Qt and the Qt logo are trademarks of Digia Plc and/or its subsidiary(-ies).

    " "

    Qt is developed as an open source project on " -- cgit v1.2.3 From ae13c4e3779163a8db5fbf7d3069913a1505bb1b Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Wed, 29 Jan 2014 17:06:01 +0100 Subject: QProcessEnvironment: Fix handling of magic environment variables The cmd shell on Windows sets special environment variables starting with a '='. Task-number: QTCREATORBUG-8716 Change-Id: Id2852188897522558907d9846fb2af069600235f Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index d728bcce94..18391703da 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -165,7 +165,7 @@ QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list QStringList::ConstIterator it = list.constBegin(), end = list.constEnd(); for ( ; it != end; ++it) { - int pos = it->indexOf(QLatin1Char('=')); + int pos = it->indexOf(QLatin1Char('='), 1); if (pos < 1) continue; -- cgit v1.2.3 From 200cc1f1e9aded9fb891e9af0699887c04a465a2 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 17 Mar 2014 19:13:08 +0100 Subject: Accessibility Mac: Fix TextEdit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtGui][Accessibility] Implemented text attributes to enable VoiceOver to read QTextEdit and QPlainTextEdit. Task-number: QTBUG-37204 Change-Id: Ie2fa8086a1bcf4907ac59850dc5c6c08b5f0b7f2 Reviewed-by: Morten Johan Sørvig --- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 66c7727f15..d32170ab01 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -121,6 +121,19 @@ [attributes addObject : NSAccessibilityValueAttribute]; } + if (iface->textInterface()) { + [attributes addObjectsFromArray: [[NSArray alloc] initWithObjects: + NSAccessibilityNumberOfCharactersAttribute, + NSAccessibilitySelectedTextAttribute, + NSAccessibilitySelectedTextRangeAttribute, + NSAccessibilityVisibleCharacterRangeAttribute, + NSAccessibilityInsertionPointLineNumberAttribute, + nil + ]]; + +// TODO: multi-selection: NSAccessibilitySelectedTextRangesAttribute, + } + return [attributes autorelease]; } @@ -167,6 +180,87 @@ return nil; return QCocoaAccessible::getValueAttribute(iface); + + } else if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute]) { + if (QAccessibleTextInterface *text = iface->textInterface()) + return [NSNumber numberWithInt: text->characterCount()]; + return nil; + } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { + if (QAccessibleTextInterface *text = iface->textInterface()) { + int start = 0; + int end = 0; + text->selection(0, &start, &end); + return text->text(start, end).toNSString(); + } + return nil; + } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { + if (QAccessibleTextInterface *text = iface->textInterface()) { + int start = 0; + int end = 0; + if (text->selectionCount() > 0) { + text->selection(0, &start, &end); + } else { + start = text->cursorPosition(); + end = start; + } + return [NSValue valueWithRange:NSMakeRange(quint32(start), quint32(end - start))]; + } + return [NSValue valueWithRange: NSMakeRange(0, 0)]; + } else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { + // FIXME This is not correct and may mostly impact performance for big texts + return [NSValue valueWithRange: NSMakeRange(0, iface->textInterface()->characterCount())]; + + } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) { + // FIXME + return nil; + } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangesAttribute]) { + // FIXME for multi-selection support + return nil; + } + + return nil; +} + +- (NSArray *)accessibilityParameterizedAttributeNames { + + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) { + qWarning() << "Called attribute on invalid object: " << axid; + return nil; + } + + if (iface->textInterface()) { + return [[NSArray alloc] initWithObjects: + NSAccessibilityStringForRangeParameterizedAttribute, +// NSAccessibilityLineForIndexParameterizedAttribute, +// NSAccessibilityRangeForLineParameterizedAttribute, +// NSAccessibilityRangeForPositionParameterizedAttribute, +// NSAccessibilityRangeForIndexParameterizedAttribute, +// NSAccessibilityBoundsForRangeParameterizedAttribute, +// NSAccessibilityRTFForRangeParameterizedAttribute, +// NSAccessibilityStyleRangeForIndexParameterizedAttribute, +// NSAccessibilityAttributedStringForRangeParameterizedAttribute, + nil + ]; + } + + return nil; +} + +- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter { + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) { + qWarning() << "Called attribute on invalid object: " << axid; + return nil; + } + + if (!iface->textInterface()) + return nil; + + if ([attribute isEqualToString: NSAccessibilityStringForRangeParameterizedAttribute]) { + NSRange range = [parameter rangeValue]; + QString text = iface->textInterface()->text(range.location, range.location + range.length); + return text.toNSString(); } return nil; -- cgit v1.2.3 From b8c96f2eb9f0cb1a5ffa8bfd3ab89f53f8e8badd Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 18 Mar 2014 17:20:23 +0100 Subject: Accessibility: Improve QTextEdit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EditableTextInterface was implemented but not reported to the accessibility bridges. Newlines in QTextEdit when using QCursor::selectedText are returned as unicode paragraphs, replace them by newlines. [ChangeLog][QtWidgets][Accessibility] Fixed QTextEdit not reporting newlines to accessibility frameworks and add editable text interface. Change-Id: Iac21e70f5468a16f8abf242ae148290dbab3f8e4 Reviewed-by: Jan Arve Sæther --- src/plugins/accessible/widgets/qaccessiblewidgets.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index 71d22eabc4..b502682938 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -144,6 +144,8 @@ void *QAccessiblePlainTextEdit::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::TextInterface) return static_cast(this); + else if (t == QAccessible::EditableTextInterface) + return static_cast(this); return QAccessibleWidget::interface_cast(t); } @@ -268,6 +270,8 @@ void *QAccessibleTextEdit::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::TextInterface) return static_cast(this); + else if (t == QAccessible::EditableTextInterface) + return static_cast(this); return QAccessibleWidget::interface_cast(t); } @@ -830,7 +834,7 @@ QString QAccessibleTextWidget::text(int startOffset, int endOffset) const cursor.setPosition(startOffset, QTextCursor::MoveAnchor); cursor.setPosition(endOffset, QTextCursor::KeepAnchor); - return cursor.selectedText(); + return cursor.selectedText().replace(QChar(QChar::ParagraphSeparator), QLatin1Char('\n')); } QPoint QAccessibleTextWidget::scrollBarPosition() const -- cgit v1.2.3 From d9697df4e0bfee651f06290fa0851255e80d7987 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 18 Mar 2014 10:52:41 +0100 Subject: Accessibility Mac: Implement setting focus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtGui][Accessibility] Allow assistive apps such as VoiceOver to set the focus on widgets and controls. Change-Id: I657bf7d827c5e5293cfd628dbb6b8f0592a84f24 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index d32170ab01..8b52c5eeff 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -268,7 +268,10 @@ - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { - return NO; // YES to handle keyboard input + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) + return nil; + return iface->state().focusable ? YES : NO; } else { return NO; } @@ -277,7 +280,10 @@ - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { Q_UNUSED(value); if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { - + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface || !iface->actionInterface()) + return; + iface->actionInterface()->doAction(QAccessibleActionInterface::setFocusAction()); } } -- cgit v1.2.3 From 04e8c5d5e886800fba764574efd2620bb5c6d789 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 18 Mar 2014 19:29:30 +0100 Subject: Accessibility Mac: Implement most TextEdit functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this patch reading QTextEdit line by line works with VoiceOver. Task-number: QTBUG-37204 Change-Id: Id9d7c4294254aaa8fe51ee8b612bfbb43348b777 Reviewed-by: Morten Johan Sørvig --- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 89 +++++++++++++++++----- 1 file changed, 68 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 8b52c5eeff..bc98d002f0 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -91,6 +91,13 @@ // attributes ++ (id) lineNumberForIndex: (int)index forText:(const QString &)text +{ + QStringRef textBefore = QStringRef(&text, 0, index); + int newlines = textBefore.count(QLatin1Char('\n')); + return [NSNumber numberWithInt: newlines]; +} + - (NSArray *)accessibilityAttributeNames { static NSArray *defaultAttributes = nil; @@ -207,14 +214,14 @@ } return [NSValue valueWithRange: NSMakeRange(0, 0)]; } else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { - // FIXME This is not correct and may mostly impact performance for big texts + // FIXME This is not correct and may impact performance for big texts return [NSValue valueWithRange: NSMakeRange(0, iface->textInterface()->characterCount())]; } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) { - // FIXME - return nil; - } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangesAttribute]) { - // FIXME for multi-selection support + if (QAccessibleTextInterface *text = iface->textInterface()) { + QString textBeforeCursor = text->text(0, text->cursorPosition()); + return [NSNumber numberWithInt: textBeforeCursor.count(QLatin1Char('\n'))]; + } return nil; } @@ -232,14 +239,14 @@ if (iface->textInterface()) { return [[NSArray alloc] initWithObjects: NSAccessibilityStringForRangeParameterizedAttribute, -// NSAccessibilityLineForIndexParameterizedAttribute, -// NSAccessibilityRangeForLineParameterizedAttribute, -// NSAccessibilityRangeForPositionParameterizedAttribute, + NSAccessibilityLineForIndexParameterizedAttribute, + NSAccessibilityRangeForLineParameterizedAttribute, + NSAccessibilityRangeForPositionParameterizedAttribute, // NSAccessibilityRangeForIndexParameterizedAttribute, -// NSAccessibilityBoundsForRangeParameterizedAttribute, + NSAccessibilityBoundsForRangeParameterizedAttribute, // NSAccessibilityRTFForRangeParameterizedAttribute, // NSAccessibilityStyleRangeForIndexParameterizedAttribute, -// NSAccessibilityAttributedStringForRangeParameterizedAttribute, + NSAccessibilityAttributedStringForRangeParameterizedAttribute, nil ]; } @@ -262,28 +269,68 @@ QString text = iface->textInterface()->text(range.location, range.location + range.length); return text.toNSString(); } - + if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) { + int index = [parameter intValue]; + NSNumber *ln = [QCocoaAccessibleElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)]; + return ln; + } + if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) { + int lineNumber = [parameter intValue]; + QString text = iface->text(QAccessible::Value); + int startOffset = 0; + // skip newlines until we have the one we look for + for (int i = 0; i < lineNumber; ++i) + startOffset = text.indexOf(QLatin1Char('\n'), startOffset) + 1; + if (startOffset < 0) // invalid line number, return the first line + startOffset = 0; + int endOffset = text.indexOf(QLatin1Char('\n'), startOffset + 1); + if (endOffset == -1) + endOffset = text.length(); + return [NSValue valueWithRange:NSMakeRange(quint32(startOffset), quint32(endOffset - startOffset))]; + } + if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) { + NSRange range = [parameter rangeValue]; + QRect firstRect = iface->textInterface()->characterRect(range.location); + QRect lastRect = iface->textInterface()->characterRect(range.location + range.length); + QRect rect = firstRect.united(lastRect); // This is off quite often, but at least a rough approximation + return [NSValue valueWithRect: NSMakeRect((CGFloat) rect.x(),(CGFloat) qt_mac_flipYCoordinate(rect.y() + rect.height()), rect.width(), rect.height())]; + } + if ([attribute isEqualToString: NSAccessibilityAttributedStringForRangeParameterizedAttribute]) { + NSRange range = [parameter rangeValue]; + QString text = iface->textInterface()->text(range.location, range.location + range.length); + return [[NSAttributedString alloc] initWithString: text.toNSString()]; + } return nil; } - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) + return nil; + if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { - QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface) - return nil; return iface->state().focusable ? YES : NO; - } else { - return NO; + } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { + return iface->textInterface() ? YES : NO; } + return NO; } - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { - Q_UNUSED(value); + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) + return; if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { - QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); - if (!iface || !iface->actionInterface()) - return; - iface->actionInterface()->doAction(QAccessibleActionInterface::setFocusAction()); + if (QAccessibleActionInterface *action = iface->actionInterface()) + action->doAction(QAccessibleActionInterface::setFocusAction()); + } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { + if (QAccessibleTextInterface *text = iface->textInterface()) { + NSRange range = [value rangeValue]; + if (range.length > 0) + text->setSelection(0, range.location, range.location + range.length); + else + text->setCursorPosition(range.location); + } } } -- cgit v1.2.3 From ecd70c038ab06e8066710b89fe9f3bf841f72111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 13 Mar 2014 13:44:44 +0100 Subject: Cocoa: call SetFrontProcess on raise() This will raise the window in front of windows from other processes as well. Following Qt 4, only do this for top-level windows. Task-number: QTBUG-29087 Change-Id: Iae1b9c2928a627501112f97728198ed6dd614b2d Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 293d3093e3..26fe9f86df 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -935,6 +935,9 @@ void QCocoaWindow::raise() [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; } else { [m_nsWindow orderFront: m_nsWindow]; + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); } } } -- cgit v1.2.3 From 91d0ba8ff438920033050e74ced8b819b2c4b057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 14 Mar 2014 11:33:07 +0100 Subject: Cococa: Make QMacNativeWidget work again. The NSWindow releasing code in recreateWindow() has regressed to not handle the m_contentViewIsToBeEmbedded case. Release the NSWindow directly instead of calling recreateWindow() Change-Id: Ibc6d10faf4c6dae42e02c400b16f28a1d28eb192 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 26fe9f86df..d8ec144ad2 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1113,7 +1113,9 @@ NSWindow *QCocoaWindow::nativeWindow() const void QCocoaWindow::setEmbeddedInForeignView(bool embedded) { m_contentViewIsToBeEmbedded = embedded; - recreateWindow(0); // destroy what was already created + // Release any previosly created NSWindow. + [m_nsWindow closeAndRelease]; + m_nsWindow = 0; } void QCocoaWindow::windowWillMove() -- cgit v1.2.3 From a791943490599b4fca3589e9782830c034e9f343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 19 Mar 2014 13:26:52 +0100 Subject: Cocoa: Follow-up m_sendUpAsRightButton for DnD Clear and test for the correct button according to the m_sendUpAsRightButton flag. (Fixes the warning mentioned QTBUG-35804) Task-number: QTBUG-35804 Change-Id: I5d724d1cfa66b88b8f54e228bd7fb73a04a9f4c9 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qnsview.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 872ae5ebbb..47081ab890 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -652,7 +652,7 @@ static QTouchDevice *touchDevice = 0; { if (m_window->flags() & Qt::WindowTransparentForInput) return [super mouseDragged:theEvent]; - if (!(m_buttons & Qt::LeftButton)) + if (!(m_buttons & (m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton))) qWarning("QNSView mouseDragged: Internal mouse button tracking invalid (missing Qt::LeftButton)"); [self handleMouseEvent:theEvent]; } @@ -1721,7 +1721,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) // keep our state, and QGuiApplication state (buttons member) in-sync, // or future mouse events will be processed incorrectly - m_buttons &= ~Qt::LeftButton; + m_buttons &= ~(m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton); NSPoint windowPoint = [self convertPoint: point fromView: nil]; QPoint qtWindowPoint(windowPoint.x, windowPoint.y); -- cgit v1.2.3 From d7eb3d128037cefeeb75adf4fe3453cf2fe565eb Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 19 Mar 2014 15:20:06 +0100 Subject: Fix creating directory hierarchy for WinRT mkpath was not working consistently on WinRT. The reason is that createDirectory() starts from C:/ which is outside the sandbox and an illegal access error has been returned. In case the chunk is still inside the "known" writable area, we continue to the next chunk. Known writable is derived from QStandardPaths. All but Temp are children of the DataLocation on WinRT. Task-number: QTBUG-35472 Change-Id: I3b4ab390bd321285da51d02f5eeaf06da4d56298 Reviewed-by: Andrew Knight --- src/corelib/io/qfilesystemengine_win.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index dbc6d28846..7741eb4c1e 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -74,6 +74,8 @@ # define SECURITY_WIN32 # include #else // !Q_OS_WINRT +# include "qstandardpaths.h" +# include "qthreadstorage.h" # include # include # include @@ -1151,6 +1153,18 @@ bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool crea bool existed = false; if (isDirPath(chunk, &existed) && existed) continue; +#ifdef Q_OS_WINRT + static QThreadStorage dataLocation; + if (!dataLocation.hasLocalData()) + dataLocation.setLocalData(QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation))); + static QThreadStorage tempLocation; + if (!tempLocation.hasLocalData()) + tempLocation.setLocalData(QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::TempLocation))); + // We try to create something outside the sandbox, which is forbidden + // However we could still try to pass into the sandbox + if (dataLocation.localData().startsWith(chunk) || tempLocation.localData().startsWith(chunk)) + continue; +#endif } return false; } -- cgit v1.2.3 From baa3d329ac0033ee1914c177347811645e79545d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 20 Mar 2014 12:24:01 +0100 Subject: Fix crash if SSL_get0_next_proto_negotiated() cannot be resolved. Crash occurs after warnings like: QSslSocket: cannot call unresolved function SSL_get0_next_proto_negotiated Task-number: QTBUG-37515 Task-number: QTBUG-33208 Change-Id: I18b803e4709b9d5f6b33717c2ac43179676351a4 Reviewed-by: Richard J. Moore Reviewed-by: Peter Hartmann --- src/network/ssl/qsslsocket_openssl.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 3421154114..bcb2254d11 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1487,11 +1487,13 @@ void QSslSocketBackendPrivate::continueHandshake() } #if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) - const unsigned char *proto; - unsigned int proto_len; + const unsigned char *proto = 0; + unsigned int proto_len = 0; q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); - QByteArray nextProtocol(reinterpret_cast(proto), proto_len); - configuration.nextNegotiatedProtocol = nextProtocol; + if (proto_len) + configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast(proto), proto_len); + else + configuration.nextNegotiatedProtocol.clear(); configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status; #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... -- cgit v1.2.3 From 503d761c0867760b96d6f7f6d44854926c6b7e0c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 28 Feb 2014 17:18:09 +0100 Subject: Print when logging rule is invalid. Print a warning when an invalid logging rule is parsed. Change-Id: I3bf9a6df4053d36b3803652b2faa86168d5222bc Reviewed-by: Friedemann Kleint --- src/corelib/io/qloggingregistry.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 23f1ffbd16..d79de3f0e8 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -224,7 +224,11 @@ void QLoggingSettingsParser::setContent(QTextStream &stream) const QStringRef value = line.midRef(equalPos + 1); bool enabled = (value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0); - _rules.append(QLoggingRule(pattern, enabled)); + QLoggingRule rule(pattern, enabled); + if (rule.flags != QLoggingRule::Invalid) + _rules.append(rule); + else + warnMsg("Ignoring malformed logging rule: '%s'", line.toUtf8().constData()); } } } -- cgit v1.2.3 From 33cac84df30770de2a2c27d4b1288a658db1b638 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 20 Mar 2014 13:22:37 +0200 Subject: ANGLE D3D11: Fix internal index buffer for level 9 hardware Some level 9 hardware does not support 32-bit indices, and in most places this is already checked. It would appear that most phone hardware actually does support 32-bit indices, and so this bug wasn't caught until testing on the Surface RT. This is not surprising, as some level 9 resources are only a minimum for the hardware spec, not the true limit of the device/driver. This patch provides the general fix to use 16-bit indices on such hardware, but a whitelist of known good GPUs should be added to enable 32-bit indices where available. Change-Id: I282ede5dd4a323037ade6c44b7cfac2c6445b491 Reviewed-by: Oliver Wolff Reviewed-by: Friedemann Kleint Reviewed-by: Maurice Kalinowski --- .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 169 ++++++++------ ...-Fix-internal-index-buffer-for-level-9-ha.patch | 256 +++++++++++++++++++++ 2 files changed, 350 insertions(+), 75 deletions(-) create mode 100644 src/angle/patches/0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch (limited to 'src') diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp index 31d976dec4..2de477b3bc 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp @@ -1137,6 +1137,84 @@ void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLv } } +template +static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) +{ + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } +} + +template +static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) +{ + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } +} + void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) { // Get the raw indices for an indexed draw @@ -1148,10 +1226,12 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, indices = static_cast(storage->getData()) + offset; } + const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) { delete mLineLoopIB; mLineLoopIB = NULL; @@ -1171,7 +1251,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType)) { ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); return gl::error(GL_OUT_OF_MEMORY); @@ -1185,42 +1265,12 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, return gl::error(GL_OUT_OF_MEMORY); } - unsigned int *data = reinterpret_cast(mappedMemory); + if (indexType == GL_UNSIGNED_SHORT) + fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); + else + fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); unsigned int indexBufferOffset = offset; - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - if (!mLineLoopIB->unmapBuffer()) { ERR("Could not unmap index buffer for GL_LINE_LOOP."); @@ -1251,10 +1301,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic indices = static_cast(storage->getData()) + offset; } + const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + if (!mTriangleFanIB) { mTriangleFanIB = new StreamingIndexBufferInterface(this); - if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) { delete mTriangleFanIB; mTriangleFanIB = NULL; @@ -1276,7 +1328,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); - if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType)) { ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); return gl::error(GL_OUT_OF_MEMORY); @@ -1290,45 +1342,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic return gl::error(GL_OUT_OF_MEMORY); } - unsigned int *data = reinterpret_cast(mappedMemory); + if (indexType == GL_UNSIGNED_SHORT) + fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); + else + fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); unsigned int indexBufferOffset = offset; - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } if (!mTriangleFanIB->unmapBuffer()) { diff --git a/src/angle/patches/0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch b/src/angle/patches/0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch new file mode 100644 index 0000000000..52dfcd6da2 --- /dev/null +++ b/src/angle/patches/0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch @@ -0,0 +1,256 @@ +From d7eb7ea643f00d47447d755b4a2125922d69a3b3 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Thu, 20 Mar 2014 13:21:29 +0200 +Subject: [PATCH] ANGLE D3D11: Fix internal index buffer for level 9 hardware + +Some level 9 hardware does not support 32-bit indices, and in most +places this is already checked. It would appear that most phone +hardware actually does support 32-bit indices, and so this bug wasn't +caught until testing on the Surface RT. This is not surprising, as some +level 9 resources are only a minimum for the hardware spec, not the +true limit of the device/driver. + +This patch provides the general fix to use 16-bit indices on such +hardware, but a whitelist of known good GPUs should be added to enable +32-bit indices where available. + +Change-Id: I282ede5dd4a323037ade6c44b7cfac2c6445b491 +--- + .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 169 ++++++++++++--------- + 1 file changed, 94 insertions(+), 75 deletions(-) + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +index 31d976d..2de477b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +@@ -1137,6 +1137,84 @@ void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLv + } + } + ++template ++static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) ++{ ++ switch (type) ++ { ++ case GL_NONE: // Non-indexed draw ++ for (int i = 0; i < count; i++) ++ { ++ data[i] = i; ++ } ++ data[count] = 0; ++ break; ++ case GL_UNSIGNED_BYTE: ++ for (int i = 0; i < count; i++) ++ { ++ data[i] = static_cast(indices)[i]; ++ } ++ data[count] = static_cast(indices)[0]; ++ break; ++ case GL_UNSIGNED_SHORT: ++ for (int i = 0; i < count; i++) ++ { ++ data[i] = static_cast(indices)[i]; ++ } ++ data[count] = static_cast(indices)[0]; ++ break; ++ case GL_UNSIGNED_INT: ++ for (int i = 0; i < count; i++) ++ { ++ data[i] = static_cast(indices)[i]; ++ } ++ data[count] = static_cast(indices)[0]; ++ break; ++ default: UNREACHABLE(); ++ } ++} ++ ++template ++static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) ++{ ++ switch (type) ++ { ++ case GL_NONE: // Non-indexed draw ++ for (unsigned int i = 0; i < numTris; i++) ++ { ++ data[i*3 + 0] = 0; ++ data[i*3 + 1] = i + 1; ++ data[i*3 + 2] = i + 2; ++ } ++ break; ++ case GL_UNSIGNED_BYTE: ++ for (unsigned int i = 0; i < numTris; i++) ++ { ++ data[i*3 + 0] = static_cast(indices)[0]; ++ data[i*3 + 1] = static_cast(indices)[i + 1]; ++ data[i*3 + 2] = static_cast(indices)[i + 2]; ++ } ++ break; ++ case GL_UNSIGNED_SHORT: ++ for (unsigned int i = 0; i < numTris; i++) ++ { ++ data[i*3 + 0] = static_cast(indices)[0]; ++ data[i*3 + 1] = static_cast(indices)[i + 1]; ++ data[i*3 + 2] = static_cast(indices)[i + 2]; ++ } ++ break; ++ case GL_UNSIGNED_INT: ++ for (unsigned int i = 0; i < numTris; i++) ++ { ++ data[i*3 + 0] = static_cast(indices)[0]; ++ data[i*3 + 1] = static_cast(indices)[i + 1]; ++ data[i*3 + 2] = static_cast(indices)[i + 2]; ++ } ++ break; ++ default: UNREACHABLE(); ++ } ++} ++ + void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) + { + // Get the raw indices for an indexed draw +@@ -1148,10 +1226,12 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, + indices = static_cast(storage->getData()) + offset; + } + ++ const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; ++ + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); +- if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) ++ if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; +@@ -1171,7 +1251,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); +- if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) ++ if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); +@@ -1185,42 +1265,12 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, + return gl::error(GL_OUT_OF_MEMORY); + } + +- unsigned int *data = reinterpret_cast(mappedMemory); ++ if (indexType == GL_UNSIGNED_SHORT) ++ fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); ++ else ++ fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); + unsigned int indexBufferOffset = offset; + +- switch (type) +- { +- case GL_NONE: // Non-indexed draw +- for (int i = 0; i < count; i++) +- { +- data[i] = i; +- } +- data[count] = 0; +- break; +- case GL_UNSIGNED_BYTE: +- for (int i = 0; i < count; i++) +- { +- data[i] = static_cast(indices)[i]; +- } +- data[count] = static_cast(indices)[0]; +- break; +- case GL_UNSIGNED_SHORT: +- for (int i = 0; i < count; i++) +- { +- data[i] = static_cast(indices)[i]; +- } +- data[count] = static_cast(indices)[0]; +- break; +- case GL_UNSIGNED_INT: +- for (int i = 0; i < count; i++) +- { +- data[i] = static_cast(indices)[i]; +- } +- data[count] = static_cast(indices)[0]; +- break; +- default: UNREACHABLE(); +- } +- + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); +@@ -1251,10 +1301,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic + indices = static_cast(storage->getData()) + offset; + } + ++ const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; ++ + if (!mTriangleFanIB) + { + mTriangleFanIB = new StreamingIndexBufferInterface(this); +- if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) ++ if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) + { + delete mTriangleFanIB; + mTriangleFanIB = NULL; +@@ -1276,7 +1328,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic + } + + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); +- if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) ++ if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType)) + { + ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); +@@ -1290,45 +1342,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic + return gl::error(GL_OUT_OF_MEMORY); + } + +- unsigned int *data = reinterpret_cast(mappedMemory); ++ if (indexType == GL_UNSIGNED_SHORT) ++ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); ++ else ++ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); + unsigned int indexBufferOffset = offset; + +- switch (type) +- { +- case GL_NONE: // Non-indexed draw +- for (unsigned int i = 0; i < numTris; i++) +- { +- data[i*3 + 0] = 0; +- data[i*3 + 1] = i + 1; +- data[i*3 + 2] = i + 2; +- } +- break; +- case GL_UNSIGNED_BYTE: +- for (unsigned int i = 0; i < numTris; i++) +- { +- data[i*3 + 0] = static_cast(indices)[0]; +- data[i*3 + 1] = static_cast(indices)[i + 1]; +- data[i*3 + 2] = static_cast(indices)[i + 2]; +- } +- break; +- case GL_UNSIGNED_SHORT: +- for (unsigned int i = 0; i < numTris; i++) +- { +- data[i*3 + 0] = static_cast(indices)[0]; +- data[i*3 + 1] = static_cast(indices)[i + 1]; +- data[i*3 + 2] = static_cast(indices)[i + 2]; +- } +- break; +- case GL_UNSIGNED_INT: +- for (unsigned int i = 0; i < numTris; i++) +- { +- data[i*3 + 0] = static_cast(indices)[0]; +- data[i*3 + 1] = static_cast(indices)[i + 1]; +- data[i*3 + 2] = static_cast(indices)[i + 2]; +- } +- break; +- default: UNREACHABLE(); +- } + + if (!mTriangleFanIB->unmapBuffer()) + { +-- +1.8.4.msysgit.0 + -- cgit v1.2.3 From 8adca56674bd51a39b278fb08f270624c825b002 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 19 Mar 2014 12:52:03 +0100 Subject: Resurrect advanced bindTexture() features in QtOpenGL During the Qt 4 -> 5 migration the setting of the extension flags in QOpenGLFunctions/Extensions suffered a regression: flags like GenerateMipmap were never set. This led to the unfortunate sitation that features that were tied to these flags, like compressed texture support or mipmap generation, got disabled. This is now corrected by checking for the extensions like Qt 4 did. Task-number: QTBUG-37588 Change-Id: I4a7beb1b435af11e05f5304aa04df2ec63b34c18 Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopenglfunctions.cpp | 45 ++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index fe6eb4c098..d52b1a314f 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -359,10 +359,37 @@ static int qt_gl_resolve_extensions() { int extensions = 0; QOpenGLExtensionMatcher extensionMatcher; + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + QSurfaceFormat format = ctx->format(); + if (extensionMatcher.match("GL_EXT_bgra")) extensions |= QOpenGLExtensions::BGRATextureFormat; - - if (QOpenGLContext::currentContext()->isES()) { + if (extensionMatcher.match("GL_ARB_texture_rectangle")) + extensions |= QOpenGLExtensions::TextureRectangle; + if (extensionMatcher.match("GL_SGIS_generate_mipmap")) + extensions |= QOpenGLExtensions::GenerateMipmap; + if (extensionMatcher.match("GL_ARB_texture_compression")) + extensions |= QOpenGLExtensions::TextureCompression; + if (extensionMatcher.match("GL_EXT_texture_compression_s3tc")) + extensions |= QOpenGLExtensions::DDSTextureCompression; + if (extensionMatcher.match("GL_OES_compressed_ETC1_RGB8_texture")) + extensions |= QOpenGLExtensions::ETC1TextureCompression; + if (extensionMatcher.match("GL_IMG_texture_compression_pvrtc")) + extensions |= QOpenGLExtensions::PVRTCTextureCompression; + if (extensionMatcher.match("GL_ARB_texture_mirrored_repeat")) + extensions |= QOpenGLExtensions::MirroredRepeat; + if (extensionMatcher.match("GL_EXT_stencil_two_side")) + extensions |= QOpenGLExtensions::StencilTwoSide; + if (extensionMatcher.match("GL_EXT_stencil_wrap")) + extensions |= QOpenGLExtensions::StencilWrap; + if (extensionMatcher.match("GL_NV_float_buffer")) + extensions |= QOpenGLExtensions::NVFloatBuffer; + if (extensionMatcher.match("GL_ARB_pixel_buffer_object")) + extensions |= QOpenGLExtensions::PixelBufferObject; + + if (ctx->isES()) { + if (format.majorVersion() >= 2) + extensions |= QOpenGLExtensions::GenerateMipmap; if (extensionMatcher.match("GL_OES_mapbuffer")) extensions |= QOpenGLExtensions::MapBuffer; if (extensionMatcher.match("GL_OES_packed_depth_stencil")) @@ -375,7 +402,6 @@ static int qt_gl_resolve_extensions() if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888")) extensions |= QOpenGLExtensions::BGRATextureFormat; } else { - QSurfaceFormat format = QOpenGLContext::currentContext()->format(); extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer; // Recognize features by extension name. @@ -394,6 +420,19 @@ static int qt_gl_resolve_extensions() extensions |= QOpenGLExtensions::PackedDepthStencil; } } + + if (format.renderableType() == QSurfaceFormat::OpenGL && format.version() >= qMakePair(3, 2)) + extensions |= QOpenGLExtensions::GeometryShaders; + +#ifndef QT_OPENGL_ES + if (extensionMatcher.match("GL_EXT_framebuffer_sRGB")) { + GLboolean srgbCapableFramebuffers = false; + ctx->functions()->glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers); + if (srgbCapableFramebuffers) + extensions |= QOpenGLExtensions::SRGBFrameBuffer; + } +#endif + return extensions; } -- cgit v1.2.3 From 3e3d06d70575b638d667d2bedae7010dbe605680 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 19 Mar 2014 13:33:40 +0100 Subject: Docs: Correct OpenGL ES naming Not sure where "OpenGL/ES" is coming from but there is no such thing. The correct name is OpenGL ES. Change-Id: If071ee5bd928fea1a2f1aebc11155344df1efe2d Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopenglfunctions.cpp | 424 ++++++++++++++++++------------------ src/opengl/qglfunctions.cpp | 338 ++++++++++++++-------------- 2 files changed, 381 insertions(+), 381 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index d52b1a314f..ef0ef6d103 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -51,12 +51,12 @@ QT_BEGIN_NAMESPACE /*! \class QOpenGLFunctions - \brief The QOpenGLFunctions class provides cross-platform access to the OpenGL/ES 2.0 API. + \brief The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API. \since 5.0 \ingroup painting-3D \inmodule QtGui - OpenGL/ES 2.0 defines a subset of the OpenGL specification that is + OpenGL ES 2.0 defines a subset of the OpenGL specification that is common across many desktop and embedded OpenGL implementations. However, it can be difficult to use the functions from that subset because they need to be resolved manually on desktop systems. @@ -102,7 +102,7 @@ QT_BEGIN_NAMESPACE } \endcode - The \c{paintGL()} function can then use any of the OpenGL/ES 2.0 + The \c{paintGL()} function can then use any of the OpenGL ES 2.0 functions without explicit resolution, such as glActiveTexture() in the following example: @@ -119,14 +119,14 @@ QT_BEGIN_NAMESPACE \endcode QOpenGLFunctions can also be used directly for ad-hoc invocation - of OpenGL/ES 2.0 functions on all platforms: + of OpenGL ES 2.0 functions on all platforms: \code QOpenGLFunctions glFuncs(QOpenGLContext::currentContext()); glFuncs.glActiveTexture(GL_TEXTURE1); \endcode - QOpenGLFunctions provides wrappers for all OpenGL/ES 2.0 + QOpenGLFunctions provides wrappers for all OpenGL ES 2.0 functions, including the common subset of OpenGL 1.x and ES 2.0. While such functions, for example glClear() or glDrawArrays(), can be called also directly, as long as the @@ -135,7 +135,7 @@ QT_BEGIN_NAMESPACE loading the OpenGL implementation. The hasOpenGLFeature() and openGLFeatures() functions can be used - to determine if the OpenGL implementation has a major OpenGL/ES 2.0 + to determine if the OpenGL implementation has a major OpenGL ES 2.0 feature. For example, the following checks if non power of two textures are available: @@ -537,7 +537,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBindTexture(\a target, \a texture). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindTexture.xml}{glBindTexture()}. \since 5.3 @@ -548,7 +548,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBlendFunc(\a sfactor, \a dfactor). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFunc.xml}{glBlendFunc()}. \since 5.3 @@ -559,7 +559,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glClear(\a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glClear.xml}{glClear()}. \since 5.3 @@ -570,7 +570,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glClearColor(\a red, \a green, \a blue, \a alpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glClearColor.xml}{glClearColor()}. \since 5.3 @@ -581,7 +581,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glClearStencil(\a s). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glClearStencil.xml}{glClearStencil()}. \since 5.3 @@ -592,7 +592,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glColorMask(\a red, \a green, \a blue, \a alpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glColorMask.xml}{glColorMask()}. \since 5.3 @@ -603,7 +603,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCopyTexImage2D(\a target, \a level, \a internalformat, \a x, \a y, \a width, \a height, \a border). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCopyTexImage2D.xml}{glCopyTexImage2D()}. \since 5.3 @@ -614,7 +614,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCopyTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a x, \a y, \a width, \a height). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCopyTexSubImage2D.xml}{glCopyTexSubImage2D()}. \since 5.3 @@ -625,7 +625,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCullFace(\a mode). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCullFace.xml}{glCullFace()}. \since 5.3 @@ -636,7 +636,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDeleteTextures(\a n, \a textures). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteTextures.xml}{glDeleteTextures()}. \since 5.3 @@ -647,7 +647,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDepthFunc(\a func). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthFunc.xml}{glDepthFunc()}. \since 5.3 @@ -658,7 +658,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDepthMask(\a flag). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthMask.xml}{glDepthMask()}. \since 5.3 @@ -669,7 +669,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDisable(\a cap). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDisable.xml}{glDisable()}. \since 5.3 @@ -680,7 +680,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDrawArrays(\a mode, \a first, \a count). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDrawArrays.xml}{glDrawArrays()}. \since 5.3 @@ -691,7 +691,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDrawElements(\a mode, \a count, \a type, \a indices). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDrawElements.xml}{glDrawElements()}. \since 5.3 @@ -702,7 +702,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glEnable(\a cap). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glEnable.xml}{glEnable()}. \since 5.3 @@ -713,7 +713,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glFinish(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFinish.xml}{glFinish()}. \since 5.3 @@ -724,7 +724,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glFlush(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFlush.xml}{glFlush()}. \since 5.3 @@ -735,7 +735,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glFrontFace(\a mode). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFrontFace.xml}{glFrontFace()}. \since 5.3 @@ -746,7 +746,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGenTextures(\a n, \a textures). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenTextures.xml}{glGenTextures()}. \since 5.3 @@ -757,7 +757,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetBooleanv(\a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBooleanv.xml}{glGetBooleanv()}. \since 5.3 @@ -768,7 +768,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetError(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetError.xml}{glGetError()}. \since 5.3 @@ -779,7 +779,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetFloatv(\a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFloatv.xml}{glGetFloatv()}. \since 5.3 @@ -790,7 +790,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetIntegerv(\a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetIntegerv.xml}{glGetIntegerv()}. \since 5.3 @@ -801,7 +801,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetString(\a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetString.xml}{glGetString()}. \since 5.3 @@ -812,7 +812,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetTexParameterfv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetTexParameterfv.xml}{glGetTexParameterfv()}. \since 5.3 @@ -823,7 +823,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetTexParameteriv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetTexParameteriv.xml}{glGetTexParameteriv()}. \since 5.3 @@ -834,7 +834,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glHint(\a target, \a mode). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glHint.xml}{glHint()}. \since 5.3 @@ -845,7 +845,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsEnabled(\a cap). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsEnabled.xml}{glIsEnabled()}. \since 5.3 @@ -856,7 +856,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsTexture(\a texture). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsTexture.xml}{glIsTexture()}. \since 5.3 @@ -867,7 +867,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glLineWidth(\a width). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glLineWidth.xml}{glLineWidth()}. \since 5.3 @@ -878,7 +878,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glPixelStorei(\a pname, \a param). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glPixelStorei.xml}{glPixelStorei()}. \since 5.3 @@ -889,7 +889,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glPolygonOffset(\a factor, \a units). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glPolygonOffset.xml}{glPolygonOffset()}. \since 5.3 @@ -900,7 +900,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glReadPixels(\a x, \a y, \a width, \a height, \a format, \a type, \a pixels). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glReadPixels.xml}{glReadPixels()}. \since 5.3 @@ -911,7 +911,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glScissor(\a x, \a y, \a width, \a height). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glScissor.xml}{glScissor()}. \since 5.3 @@ -922,7 +922,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glStencilFunc(\a func, \a ref, \a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFunc.xml}{glStencilFunc()}. \since 5.3 @@ -933,7 +933,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glStencilMask(\a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMask.xml}{glStencilMask()}. \since 5.3 @@ -944,7 +944,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glStencilOp(\a fail, \a zfail, \a zpass). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOp.xml}{glStencilOp()}. \since 5.3 @@ -955,7 +955,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a format, \a type, \a pixels). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glTexImage2D.xml}{glTexImage2D()}. \since 5.3 @@ -966,7 +966,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glTexParameterf(\a target, \a pname, \a param). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glTexParameterf.xml}{glTexParameterf()}. \since 5.3 @@ -977,7 +977,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glTexParameterfv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glTexParameterfv.xml}{glTexParameterfv()}. \since 5.3 @@ -988,7 +988,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glTexParameteri(\a target, \a pname, \a param). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glTexParameteri.xml}{glTexParameteri()}. \since 5.3 @@ -999,7 +999,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glTexParameteriv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glTexParameteriv.xml}{glTexParameteriv()}. \since 5.3 @@ -1010,7 +1010,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a type, \a pixels). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glTexSubImage2D.xml}{glTexSubImage2D()}. \since 5.3 @@ -1021,7 +1021,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glViewport(\a x, \a y, \a width, \a height). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glViewport.xml}{glViewport()}. \since 5.3 @@ -1032,7 +1032,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glActiveTexture(\a texture). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glActiveTexture.xml}{glActiveTexture()}. */ @@ -1041,10 +1041,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glAttachShader(\a program, \a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glAttachShader.xml}{glAttachShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1052,10 +1052,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBindAttribLocation(\a program, \a index, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindAttribLocation.xml}{glBindAttribLocation()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1063,7 +1063,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBindBuffer(\a target, \a buffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindBuffer.xml}{glBindBuffer()}. */ @@ -1075,7 +1075,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Note that Qt will translate a \a framebuffer argument of 0 to the currently bound QOpenGLContext's defaultFramebufferObject(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}. */ @@ -1084,7 +1084,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBindRenderbuffer(\a target, \a renderbuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindRenderbuffer.xml}{glBindRenderbuffer()}. */ @@ -1093,7 +1093,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBlendColor(\a red, \a green, \a blue, \a alpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendColor.xml}{glBlendColor()}. */ @@ -1102,7 +1102,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBlendEquation(\a mode). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquation.xml}{glBlendEquation()}. */ @@ -1111,7 +1111,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBlendEquationSeparate(\a modeRGB, \a modeAlpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquationSeparate.xml}{glBlendEquationSeparate()}. */ @@ -1120,7 +1120,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBlendFuncSeparate(\a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFuncSeparate.xml}{glBlendFuncSeparate()}. */ @@ -1129,7 +1129,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBufferData(\a target, \a size, \a data, \a usage). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferData.xml}{glBufferData()}. */ @@ -1138,7 +1138,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glBufferSubData(\a target, \a offset, \a size, \a data). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferSubData.xml}{glBufferSubData()}. */ @@ -1147,7 +1147,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCheckFramebufferStatus(\a target). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCheckFramebufferStatus.xml}{glCheckFramebufferStatus()}. */ @@ -1156,9 +1156,9 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glClearDepth(\a depth) on desktop OpenGL systems and glClearDepthf(\a depth) on - embedded OpenGL/ES systems. + embedded OpenGL ES systems. - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glClearDepthf.xml}{glClearDepthf()}. */ @@ -1167,10 +1167,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCompileShader(\a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCompileShader.xml}{glCompileShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1178,7 +1178,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCompressedTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a imageSize, \a data). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexImage2D.xml}{glCompressedTexImage2D()}. */ @@ -1187,7 +1187,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCompressedTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a imageSize, \a data). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexSubImage2D.xml}{glCompressedTexSubImage2D()}. */ @@ -1196,10 +1196,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCreateProgram(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateProgram.xml}{glCreateProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1207,10 +1207,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glCreateShader(\a type). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateShader.xml}{glCreateShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1218,7 +1218,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDeleteBuffers(\a n, \a buffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteBuffers.xml}{glDeleteBuffers()}. */ @@ -1227,7 +1227,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDeleteFramebuffers(\a n, \a framebuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteFramebuffers.xml}{glDeleteFramebuffers()}. */ @@ -1236,10 +1236,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDeleteProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteProgram.xml}{glDeleteProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1247,7 +1247,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDeleteRenderbuffers(\a n, \a renderbuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteRenderbuffers.xml}{glDeleteRenderbuffers()}. */ @@ -1256,10 +1256,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDeleteShader(\a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteShader.xml}{glDeleteShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1267,9 +1267,9 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDepthRange(\a zNear, \a zFar) on desktop OpenGL systems and glDepthRangef(\a zNear, \a zFar) on - embedded OpenGL/ES systems. + embedded OpenGL ES systems. - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthRangef.xml}{glDepthRangef()}. */ @@ -1278,10 +1278,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDetachShader(\a program, \a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDetachShader.xml}{glDetachShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1289,10 +1289,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glDisableVertexAttribArray(\a index). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDisableVertexAttribArray.xml}{glDisableVertexAttribArray()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1300,10 +1300,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glEnableVertexAttribArray(\a index). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glEnableVertexAttribArray.xml}{glEnableVertexAttribArray()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1311,7 +1311,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glFramebufferRenderbuffer(\a target, \a attachment, \a renderbuffertarget, \a renderbuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferRenderbuffer.xml}{glFramebufferRenderbuffer()}. */ @@ -1320,7 +1320,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glFramebufferTexture2D(\a target, \a attachment, \a textarget, \a texture, \a level). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferTexture2D.xml}{glFramebufferTexture2D()}. */ @@ -1329,7 +1329,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGenBuffers(\a n, \a buffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenBuffers.xml}{glGenBuffers()}. */ @@ -1338,7 +1338,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGenerateMipmap(\a target). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenerateMipmap.xml}{glGenerateMipmap()}. */ @@ -1347,7 +1347,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGenFramebuffers(\a n, \a framebuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenFramebuffers.xml}{glGenFramebuffers()}. */ @@ -1356,7 +1356,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGenRenderbuffers(\a n, \a renderbuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenRenderbuffers.xml}{glGenRenderbuffers()}. */ @@ -1365,10 +1365,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetActiveAttrib(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveAttrib.xml}{glGetActiveAttrib()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1376,10 +1376,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetActiveUniform(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveUniform.xml}{glGetActiveUniform()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1387,10 +1387,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetAttachedShaders(\a program, \a maxcount, \a count, \a shaders). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttachedShaders.xml}{glGetAttachedShaders()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1398,10 +1398,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetAttribLocation(\a program, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttribLocation.xml}{glGetAttribLocation()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1409,7 +1409,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetBufferParameteriv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBufferParameteriv.xml}{glGetBufferParameteriv()}. */ @@ -1418,7 +1418,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetFramebufferAttachmentParameteriv(\a target, \a attachment, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFramebufferAttachmentParameteriv.xml}{glGetFramebufferAttachmentParameteriv()}. */ @@ -1427,10 +1427,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetProgramiv(\a program, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramiv.xml}{glGetProgramiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1438,10 +1438,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetProgramInfoLog(\a program, \a bufsize, \a length, \a infolog). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramInfoLog.xml}{glGetProgramInfoLog()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1449,7 +1449,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetRenderbufferParameteriv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetRenderbufferParameteriv.xml}{glGetRenderbufferParameteriv()}. */ @@ -1458,10 +1458,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetShaderiv(\a shader, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderiv.xml}{glGetShaderiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1469,10 +1469,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetShaderInfoLog(\a shader, \a bufsize, \a length, \a infolog). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderInfoLog.xml}{glGetShaderInfoLog()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1480,10 +1480,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetShaderPrecisionFormat(\a shadertype, \a precisiontype, \a range, \a precision). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderPrecisionFormat.xml}{glGetShaderPrecisionFormat()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1491,10 +1491,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetShaderSource(\a shader, \a bufsize, \a length, \a source). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderSource.xml}{glGetShaderSource()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1502,10 +1502,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetUniformfv(\a program, \a location, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformfv.xml}{glGetUniformfv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1513,10 +1513,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetUniformiv(\a program, \a location, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformiv.xml}{glGetUniformiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1524,10 +1524,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetUniformLocation(\a program, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformLocation.xml}{glGetUniformLocation()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1535,10 +1535,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetVertexAttribfv(\a index, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribfv.xml}{glGetVertexAttribfv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1546,10 +1546,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetVertexAttribiv(\a index, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribiv.xml}{glGetVertexAttribiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1557,10 +1557,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glGetVertexAttribPointerv(\a index, \a pname, \a pointer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribPointerv.xml}{glGetVertexAttribPointerv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1568,7 +1568,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsBuffer(\a buffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsBuffer.xml}{glIsBuffer()}. */ @@ -1577,7 +1577,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsFramebuffer(\a framebuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsFramebuffer.xml}{glIsFramebuffer()}. */ @@ -1586,10 +1586,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsProgram.xml}{glIsProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1597,7 +1597,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsRenderbuffer(\a renderbuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsRenderbuffer.xml}{glIsRenderbuffer()}. */ @@ -1606,10 +1606,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glIsShader(\a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsShader.xml}{glIsShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1617,10 +1617,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glLinkProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glLinkProgram.xml}{glLinkProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1628,10 +1628,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glReleaseShaderCompiler(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glReleaseShaderCompiler.xml}{glReleaseShaderCompiler()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1639,7 +1639,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glRenderbufferStorage(\a target, \a internalformat, \a width, \a height). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glRenderbufferStorage.xml}{glRenderbufferStorage()}. */ @@ -1648,7 +1648,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glSampleCoverage(\a value, \a invert). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glSampleCoverage.xml}{glSampleCoverage()}. */ @@ -1657,10 +1657,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glShaderBinary(\a n, \a shaders, \a binaryformat, \a binary, \a length). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderBinary.xml}{glShaderBinary()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1668,10 +1668,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glShaderSource(\a shader, \a count, \a string, \a length). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderSource.xml}{glShaderSource()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1679,7 +1679,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glStencilFuncSeparate(\a face, \a func, \a ref, \a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFuncSeparate.xml}{glStencilFuncSeparate()}. */ @@ -1688,7 +1688,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glStencilMaskSeparate(\a face, \a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMaskSeparate.xml}{glStencilMaskSeparate()}. */ @@ -1697,7 +1697,7 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glStencilOpSeparate(\a face, \a fail, \a zfail, \a zpass). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOpSeparate.xml}{glStencilOpSeparate()}. */ @@ -1706,10 +1706,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform1f(\a location, \a x). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1f.xml}{glUniform1f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1717,10 +1717,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform1fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1fv.xml}{glUniform1fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1728,10 +1728,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform1i(\a location, \a x). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1i.xml}{glUniform1i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1739,10 +1739,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform1iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1iv.xml}{glUniform1iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1750,10 +1750,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform2f(\a location, \a x, \a y). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2f.xml}{glUniform2f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1761,10 +1761,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform2fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2fv.xml}{glUniform2fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1772,10 +1772,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform2i(\a location, \a x, \a y). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2i.xml}{glUniform2i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1783,10 +1783,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform2iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2iv.xml}{glUniform2iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1794,10 +1794,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform3f(\a location, \a x, \a y, \a z). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3f.xml}{glUniform3f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1805,10 +1805,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform3fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3fv.xml}{glUniform3fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1816,10 +1816,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform3i(\a location, \a x, \a y, \a z). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3i.xml}{glUniform3i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1827,10 +1827,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform3iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3iv.xml}{glUniform3iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1838,10 +1838,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform4f(\a location, \a x, \a y, \a z, \a w). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4f.xml}{glUniform4f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1849,10 +1849,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform4fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4fv.xml}{glUniform4fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1860,10 +1860,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform4i(\a location, \a x, \a y, \a z, \a w). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4i.xml}{glUniform4i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1871,10 +1871,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniform4iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4iv.xml}{glUniform4iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1882,10 +1882,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniformMatrix2fv(\a location, \a count, \a transpose, \a value). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix2fv.xml}{glUniformMatrix2fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1893,10 +1893,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniformMatrix3fv(\a location, \a count, \a transpose, \a value). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix3fv.xml}{glUniformMatrix3fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1904,10 +1904,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUniformMatrix4fv(\a location, \a count, \a transpose, \a value). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix4fv.xml}{glUniformMatrix4fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1915,10 +1915,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glUseProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUseProgram.xml}{glUseProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1926,10 +1926,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glValidateProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glValidateProgram.xml}{glValidateProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1937,10 +1937,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib1f(\a indx, \a x). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1f.xml}{glVertexAttrib1f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1948,10 +1948,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib1fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1fv.xml}{glVertexAttrib1fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1959,10 +1959,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib2f(\a indx, \a x, \a y). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2f.xml}{glVertexAttrib2f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1970,10 +1970,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib2fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2fv.xml}{glVertexAttrib2fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1981,10 +1981,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib3f(\a indx, \a x, \a y, \a z). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3f.xml}{glVertexAttrib3f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1992,10 +1992,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib3fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3fv.xml}{glVertexAttrib3fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -2003,10 +2003,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib4f(\a indx, \a x, \a y, \a z, \a w). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4f.xml}{glVertexAttrib4f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -2014,10 +2014,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttrib4fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4fv.xml}{glVertexAttrib4fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -2025,10 +2025,10 @@ void QOpenGLFunctions::initializeOpenGLFunctions() Convenience function that calls glVertexAttribPointer(\a indx, \a size, \a type, \a normalized, \a stride, \a ptr). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttribPointer.xml}{glVertexAttribPointer()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp index d82e55eba1..450f17b171 100644 --- a/src/opengl/qglfunctions.cpp +++ b/src/opengl/qglfunctions.cpp @@ -49,12 +49,12 @@ QT_BEGIN_NAMESPACE /*! \class QGLFunctions \inmodule QtOpenGL - \brief The QGLFunctions class provides cross-platform access to the OpenGL/ES 2.0 API. + \brief The QGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API. \since 4.8 \obsolete \ingroup painting-3D - OpenGL/ES 2.0 defines a subset of the OpenGL specification that is + OpenGL ES 2.0 defines a subset of the OpenGL specification that is common across many desktop and embedded OpenGL implementations. However, it can be difficult to use the functions from that subset because they need to be resolved manually on desktop systems. @@ -82,7 +82,7 @@ QT_BEGIN_NAMESPACE } \endcode - The \c{paintGL()} function can then use any of the OpenGL/ES 2.0 + The \c{paintGL()} function can then use any of the OpenGL ES 2.0 functions without explicit resolution, such as glActiveTexture() in the following example: @@ -96,23 +96,23 @@ QT_BEGIN_NAMESPACE \endcode QGLFunctions can also be used directly for ad-hoc invocation - of OpenGL/ES 2.0 functions on all platforms: + of OpenGL ES 2.0 functions on all platforms: \code QGLFunctions glFuncs(QGLContext::currentContext()); glFuncs.glActiveTexture(GL_TEXTURE1); \endcode - QGLFunctions provides wrappers for all OpenGL/ES 2.0 functions, + QGLFunctions provides wrappers for all OpenGL ES 2.0 functions, except those like \c{glDrawArrays()}, \c{glViewport()}, and \c{glBindTexture()} that don't have portability issues. Including the header for QGLFunctions will also define all of - the OpenGL/ES 2.0 macro constants that are not already defined by + the OpenGL ES 2.0 macro constants that are not already defined by the system's OpenGL headers, such as \c{GL_TEXTURE1} above. The hasOpenGLFeature() and openGLFeatures() functions can be used - to determine if the OpenGL implementation has a major OpenGL/ES 2.0 + to determine if the OpenGL implementation has a major OpenGL ES 2.0 feature. For example, the following checks if non power of two textures are available: @@ -126,7 +126,7 @@ QT_BEGIN_NAMESPACE /*! \enum QGLFunctions::OpenGLFeature - This enum defines OpenGL/ES 2.0 features that may be optional + This enum defines OpenGL ES 2.0 features that may be optional on other platforms. \value Multitexture glActiveTexture() function is available. @@ -373,7 +373,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glActiveTexture(\a texture). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glActiveTexture.xml}{glActiveTexture()}. */ @@ -382,10 +382,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glAttachShader(\a program, \a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glAttachShader.xml}{glAttachShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -393,10 +393,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBindAttribLocation(\a program, \a index, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindAttribLocation.xml}{glBindAttribLocation()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -404,7 +404,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBindBuffer(\a target, \a buffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindBuffer.xml}{glBindBuffer()}. */ @@ -416,7 +416,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Note that Qt will translate a \a framebuffer argument of 0 to the currently bound QOpenGLContext's defaultFramebufferObject(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}. */ @@ -425,7 +425,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBindRenderbuffer(\a target, \a renderbuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBindRenderbuffer.xml}{glBindRenderbuffer()}. */ @@ -434,7 +434,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBlendColor(\a red, \a green, \a blue, \a alpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendColor.xml}{glBlendColor()}. */ @@ -443,7 +443,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBlendEquation(\a mode). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquation.xml}{glBlendEquation()}. */ @@ -452,7 +452,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBlendEquationSeparate(\a modeRGB, \a modeAlpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquationSeparate.xml}{glBlendEquationSeparate()}. */ @@ -461,7 +461,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBlendFuncSeparate(\a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFuncSeparate.xml}{glBlendFuncSeparate()}. */ @@ -470,7 +470,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBufferData(\a target, \a size, \a data, \a usage). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferData.xml}{glBufferData()}. */ @@ -479,7 +479,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glBufferSubData(\a target, \a offset, \a size, \a data). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferSubData.xml}{glBufferSubData()}. */ @@ -488,7 +488,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glCheckFramebufferStatus(\a target). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCheckFramebufferStatus.xml}{glCheckFramebufferStatus()}. */ @@ -497,9 +497,9 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glClearDepth(\a depth) on desktop OpenGL systems and glClearDepthf(\a depth) on - embedded OpenGL/ES systems. + embedded OpenGL ES systems. - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glClearDepthf.xml}{glClearDepthf()}. */ @@ -508,10 +508,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glCompileShader(\a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCompileShader.xml}{glCompileShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -519,7 +519,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glCompressedTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a imageSize, \a data). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexImage2D.xml}{glCompressedTexImage2D()}. */ @@ -528,7 +528,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glCompressedTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a imageSize, \a data). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexSubImage2D.xml}{glCompressedTexSubImage2D()}. */ @@ -537,10 +537,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glCreateProgram(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateProgram.xml}{glCreateProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -548,10 +548,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glCreateShader(\a type). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateShader.xml}{glCreateShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -559,7 +559,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDeleteBuffers(\a n, \a buffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteBuffers.xml}{glDeleteBuffers()}. */ @@ -568,7 +568,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDeleteFramebuffers(\a n, \a framebuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteFramebuffers.xml}{glDeleteFramebuffers()}. */ @@ -577,10 +577,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDeleteProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteProgram.xml}{glDeleteProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -588,7 +588,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDeleteRenderbuffers(\a n, \a renderbuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteRenderbuffers.xml}{glDeleteRenderbuffers()}. */ @@ -597,10 +597,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDeleteShader(\a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteShader.xml}{glDeleteShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -608,9 +608,9 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDepthRange(\a zNear, \a zFar) on desktop OpenGL systems and glDepthRangef(\a zNear, \a zFar) on - embedded OpenGL/ES systems. + embedded OpenGL ES systems. - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthRangef.xml}{glDepthRangef()}. */ @@ -619,10 +619,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDetachShader(\a program, \a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDetachShader.xml}{glDetachShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -630,10 +630,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glDisableVertexAttribArray(\a index). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glDisableVertexAttribArray.xml}{glDisableVertexAttribArray()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -641,10 +641,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glEnableVertexAttribArray(\a index). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glEnableVertexAttribArray.xml}{glEnableVertexAttribArray()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -652,7 +652,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glFramebufferRenderbuffer(\a target, \a attachment, \a renderbuffertarget, \a renderbuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferRenderbuffer.xml}{glFramebufferRenderbuffer()}. */ @@ -661,7 +661,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glFramebufferTexture2D(\a target, \a attachment, \a textarget, \a texture, \a level). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferTexture2D.xml}{glFramebufferTexture2D()}. */ @@ -670,7 +670,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGenBuffers(\a n, \a buffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenBuffers.xml}{glGenBuffers()}. */ @@ -679,7 +679,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGenerateMipmap(\a target). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenerateMipmap.xml}{glGenerateMipmap()}. */ @@ -688,7 +688,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGenFramebuffers(\a n, \a framebuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenFramebuffers.xml}{glGenFramebuffers()}. */ @@ -697,7 +697,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGenRenderbuffers(\a n, \a renderbuffers). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGenRenderbuffers.xml}{glGenRenderbuffers()}. */ @@ -706,10 +706,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetActiveAttrib(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveAttrib.xml}{glGetActiveAttrib()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -717,10 +717,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetActiveUniform(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveUniform.xml}{glGetActiveUniform()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -728,10 +728,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetAttachedShaders(\a program, \a maxcount, \a count, \a shaders). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttachedShaders.xml}{glGetAttachedShaders()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -739,10 +739,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetAttribLocation(\a program, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttribLocation.xml}{glGetAttribLocation()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -750,7 +750,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetBufferParameteriv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBufferParameteriv.xml}{glGetBufferParameteriv()}. */ @@ -759,7 +759,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetFramebufferAttachmentParameteriv(\a target, \a attachment, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFramebufferAttachmentParameteriv.xml}{glGetFramebufferAttachmentParameteriv()}. */ @@ -768,10 +768,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetProgramiv(\a program, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramiv.xml}{glGetProgramiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -779,10 +779,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetProgramInfoLog(\a program, \a bufsize, \a length, \a infolog). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramInfoLog.xml}{glGetProgramInfoLog()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -790,7 +790,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetRenderbufferParameteriv(\a target, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetRenderbufferParameteriv.xml}{glGetRenderbufferParameteriv()}. */ @@ -799,10 +799,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetShaderiv(\a shader, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderiv.xml}{glGetShaderiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -810,10 +810,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetShaderInfoLog(\a shader, \a bufsize, \a length, \a infolog). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderInfoLog.xml}{glGetShaderInfoLog()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -821,10 +821,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetShaderPrecisionFormat(\a shadertype, \a precisiontype, \a range, \a precision). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderPrecisionFormat.xml}{glGetShaderPrecisionFormat()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -832,10 +832,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetShaderSource(\a shader, \a bufsize, \a length, \a source). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderSource.xml}{glGetShaderSource()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -843,10 +843,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetUniformfv(\a program, \a location, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformfv.xml}{glGetUniformfv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -854,10 +854,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetUniformiv(\a program, \a location, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformiv.xml}{glGetUniformiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -865,10 +865,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetUniformLocation(\a program, \a name). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformLocation.xml}{glGetUniformLocation()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -876,10 +876,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetVertexAttribfv(\a index, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribfv.xml}{glGetVertexAttribfv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -887,10 +887,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetVertexAttribiv(\a index, \a pname, \a params). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribiv.xml}{glGetVertexAttribiv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -898,10 +898,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glGetVertexAttribPointerv(\a index, \a pname, \a pointer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribPointerv.xml}{glGetVertexAttribPointerv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -909,7 +909,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glIsBuffer(\a buffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsBuffer.xml}{glIsBuffer()}. */ @@ -918,7 +918,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glIsFramebuffer(\a framebuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsFramebuffer.xml}{glIsFramebuffer()}. */ @@ -927,10 +927,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glIsProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsProgram.xml}{glIsProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -938,7 +938,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glIsRenderbuffer(\a renderbuffer). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsRenderbuffer.xml}{glIsRenderbuffer()}. */ @@ -947,10 +947,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glIsShader(\a shader). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glIsShader.xml}{glIsShader()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -958,10 +958,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glLinkProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glLinkProgram.xml}{glLinkProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -969,10 +969,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glReleaseShaderCompiler(). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glReleaseShaderCompiler.xml}{glReleaseShaderCompiler()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -980,7 +980,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glRenderbufferStorage(\a target, \a internalformat, \a width, \a height). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glRenderbufferStorage.xml}{glRenderbufferStorage()}. */ @@ -989,7 +989,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glSampleCoverage(\a value, \a invert). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glSampleCoverage.xml}{glSampleCoverage()}. */ @@ -998,10 +998,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glShaderBinary(\a n, \a shaders, \a binaryformat, \a binary, \a length). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderBinary.xml}{glShaderBinary()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1009,10 +1009,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glShaderSource(\a shader, \a count, \a string, \a length). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderSource.xml}{glShaderSource()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1020,7 +1020,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glStencilFuncSeparate(\a face, \a func, \a ref, \a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFuncSeparate.xml}{glStencilFuncSeparate()}. */ @@ -1029,7 +1029,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glStencilMaskSeparate(\a face, \a mask). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMaskSeparate.xml}{glStencilMaskSeparate()}. */ @@ -1038,7 +1038,7 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glStencilOpSeparate(\a face, \a fail, \a zfail, \a zpass). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOpSeparate.xml}{glStencilOpSeparate()}. */ @@ -1047,10 +1047,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform1f(\a location, \a x). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1f.xml}{glUniform1f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1058,10 +1058,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform1fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1fv.xml}{glUniform1fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1069,10 +1069,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform1i(\a location, \a x). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1i.xml}{glUniform1i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1080,10 +1080,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform1iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1iv.xml}{glUniform1iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1091,10 +1091,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform2f(\a location, \a x, \a y). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2f.xml}{glUniform2f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1102,10 +1102,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform2fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2fv.xml}{glUniform2fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1113,10 +1113,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform2i(\a location, \a x, \a y). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2i.xml}{glUniform2i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1124,10 +1124,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform2iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2iv.xml}{glUniform2iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1135,10 +1135,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform3f(\a location, \a x, \a y, \a z). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3f.xml}{glUniform3f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1146,10 +1146,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform3fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3fv.xml}{glUniform3fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1157,10 +1157,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform3i(\a location, \a x, \a y, \a z). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3i.xml}{glUniform3i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1168,10 +1168,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform3iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3iv.xml}{glUniform3iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1179,10 +1179,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform4f(\a location, \a x, \a y, \a z, \a w). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4f.xml}{glUniform4f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1190,10 +1190,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform4fv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4fv.xml}{glUniform4fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1201,10 +1201,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform4i(\a location, \a x, \a y, \a z, \a w). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4i.xml}{glUniform4i()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1212,10 +1212,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniform4iv(\a location, \a count, \a v). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4iv.xml}{glUniform4iv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1223,10 +1223,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniformMatrix2fv(\a location, \a count, \a transpose, \a value). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix2fv.xml}{glUniformMatrix2fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1234,10 +1234,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniformMatrix3fv(\a location, \a count, \a transpose, \a value). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix3fv.xml}{glUniformMatrix3fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1245,10 +1245,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUniformMatrix4fv(\a location, \a count, \a transpose, \a value). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix4fv.xml}{glUniformMatrix4fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1256,10 +1256,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glUseProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glUseProgram.xml}{glUseProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1267,10 +1267,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glValidateProgram(\a program). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glValidateProgram.xml}{glValidateProgram()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1278,10 +1278,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib1f(\a indx, \a x). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1f.xml}{glVertexAttrib1f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1289,10 +1289,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib1fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1fv.xml}{glVertexAttrib1fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1300,10 +1300,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib2f(\a indx, \a x, \a y). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2f.xml}{glVertexAttrib2f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1311,10 +1311,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib2fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2fv.xml}{glVertexAttrib2fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1322,10 +1322,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib3f(\a indx, \a x, \a y, \a z). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3f.xml}{glVertexAttrib3f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1333,10 +1333,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib3fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3fv.xml}{glVertexAttrib3fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1344,10 +1344,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib4f(\a indx, \a x, \a y, \a z, \a w). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4f.xml}{glVertexAttrib4f()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1355,10 +1355,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttrib4fv(\a indx, \a values). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4fv.xml}{glVertexAttrib4fv()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ /*! @@ -1366,10 +1366,10 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context) Convenience function that calls glVertexAttribPointer(\a indx, \a size, \a type, \a normalized, \a stride, \a ptr). - For more information, see the OpenGL/ES 2.0 documentation for + For more information, see the OpenGL ES 2.0 documentation for \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttribPointer.xml}{glVertexAttribPointer()}. - This convenience function will do nothing on OpenGL/ES 1.x systems. + This convenience function will do nothing on OpenGL ES 1.x systems. */ QGLFunctionsPrivate::QGLFunctionsPrivate(const QGLContext *) -- cgit v1.2.3 From 5bcb87babf3fa416375ada549108855b74be6a7b Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 19 Mar 2014 23:08:20 +0100 Subject: QApplication: fix scroll phase handling for wheel events Set scroll phase correctly for propagated wheel events, and do not let Qt::ScrollBegin/End steal focus when using Qt::WheelFocus policy. Change-Id: Ia38b64059d96a228c3b83c9b455db6e30dfb9a46 Reviewed-by: Gabriel de Dietrich --- src/widgets/kernel/qapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index cb6f4aeecd..6cc4e704fb 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3097,12 +3097,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint relpos = wheel->pos(); bool eventAccepted = wheel->isAccepted(); - if (e->spontaneous()) + if (e->spontaneous() && wheel->phase() == Qt::ScrollUpdate) QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); while (w) { QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers()); + wheel->modifiers(), wheel->phase()); we.spont = wheel->spontaneous(); res = d->notify_helper(w, w == receiver ? wheel : &we); eventAccepted = ((w == receiver) ? wheel : &we)->isAccepted(); -- cgit v1.2.3 From ff0e7df477ac8400c1fde8c477d721c01d949175 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 19 Mar 2014 17:21:29 +0100 Subject: Stop omitted enum value from showing up in Qt namespace doc. The following omitted enum description can be seen at [1]: "Ensures that the longest variant is always used when computing the size of a multi-variant string. (Internal)" This is because \omitvalue does not allow a description (whereas \value does). The description was moved to the qnamespace.h as a code comment. [1] http://qt-project.org/doc/qt-5/qt.html#TextFlag-enum Change-Id: I7983613bffa90f3071a4e2d678696391048c8757 Reviewed-by: Martin Smith --- src/corelib/global/qnamespace.h | 2 ++ src/corelib/global/qnamespace.qdoc | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index d7ae97e911..839d352d36 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -267,6 +267,8 @@ public: TextJustificationForced = 0x10000, TextForceLeftToRight = 0x20000, TextForceRightToLeft = 0x40000, + // Ensures that the longest variant is always used when computing the + // size of a multi-variant string. TextLongestVariant = 0x80000, TextBypassShaping = 0x100000 }; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 31bc18749b..8ade3f86d6 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -493,8 +493,7 @@ text; otherwise this width is excluded. \value TextJustificationForced Ensures that text lines are justified. - \omitvalue TextLongestVariant Ensures that the longest variant is always used - when computing the size of a multi-variant string. (Internal) + \omitvalue TextLongestVariant \omitvalue TextBypassShaping \omitvalue TextForceLeftToRight \omitvalue TextForceRightToLeft -- cgit v1.2.3 From 9ad768fd1999780df18551151b9d9fa9c354131c Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 20 Mar 2014 13:54:03 +0100 Subject: QPushButton: draw label using the stylesheet's font. The RenderRule for the stylesheet has the correct font information, it just wasn't being set on the painter that draws the label. Task-number: QTBUG-8990 Change-Id: I7cbaffc570421db04ebf3254cb6a21a68f7b868b Reviewed-by: Andy Shaw Reviewed-by: Jens Bache-Wiig --- src/widgets/styles/qstylesheetstyle.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 6bd0ba37c8..94f8e36235 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3382,6 +3382,11 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q if (const QStyleOptionButton *button = qstyleoption_cast(opt)) { QStyleOptionButton butOpt(*button); rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button); + + const QFont oldFont = p->font(); + if (rule.hasFont) + p->setFont(rule.font); + if (rule.hasPosition() && rule.position()->textAlignment != 0) { Qt::Alignment textAlignment = rule.position()->textAlignment; QRect textRect = button->rect; @@ -3454,6 +3459,9 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q } else { ParentStyle::drawControl(ce, &butOpt, p, w); } + + if (rule.hasFont) + p->setFont(oldFont); } return; -- cgit v1.2.3 From 07fef5f3ffd83ebece224e7fccac6749b3fc6cf7 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 18 Mar 2014 16:05:15 +0100 Subject: QFusionStyle: support transient scrollbars QFusionStyle doesn't make scrollbars transient by default, but the feature can be enabled with a proxy style: class MyProxyStyle : public QProxyStyle { public: int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, QStyleHintReturn *ret = 0) const { if (sh == QStyle::SH_ScrollBar_Transient) return 1; return QProxyStyle::styleHint(sh, opt, w, ret); } }; Change-Id: Ibf169e219ad920cbe7edb06e128e09ed4d8faf96 Reviewed-by: Jens Bache-Wiig --- src/widgets/styles/qcommonstyle.cpp | 4 +- src/widgets/styles/qfusionstyle.cpp | 196 ++++++++++++++++++++++++++++++------ 2 files changed, 168 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 2be0cdb9b6..f1cf46169a 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -3939,7 +3939,9 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex case CC_ScrollBar: if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(opt)) { const QRect scrollBarRect = scrollbar->rect; - int sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget); + int sbextent = 0; + if (!proxy()->styleHint(SH_ScrollBar_Transient, scrollbar, widget)) + sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget); int maxlen = ((scrollbar->orientation == Qt::Horizontal) ? scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2); int sliderlen; diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index c4bc5a5e96..2172c9082f 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -2393,6 +2393,91 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption case CC_ScrollBar: painter->save(); if (const QStyleOptionSlider *scrollBar = qstyleoption_cast(option)) { + bool wasActive = false; + qreal expandScale = 1.0; + qreal expandOffset = -1.0; + QObject *styleObject = option->styleObject; + if (styleObject && proxy()->styleHint(SH_ScrollBar_Transient, option, widget)) { + qreal opacity = 0.0; + bool shouldExpand = false; + const qreal maxExpandScale = 13.0 / 9.0; + + int oldPos = styleObject->property("_q_stylepos").toInt(); + int oldMin = styleObject->property("_q_stylemin").toInt(); + int oldMax = styleObject->property("_q_stylemax").toInt(); + QRect oldRect = styleObject->property("_q_stylerect").toRect(); + int oldState = styleObject->property("_q_stylestate").toInt(); + uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); + + // a scrollbar is transient when the the scrollbar itself and + // its sibling are both inactive (ie. not pressed/hovered/moved) + bool transient = !option->activeSubControls && !(option->state & State_On); + + if (!transient || + oldPos != scrollBar->sliderPosition || + oldMin != scrollBar->minimum || + oldMax != scrollBar->maximum || + oldRect != scrollBar->rect || + oldState != scrollBar->state || + oldActiveControls != scrollBar->activeSubControls) { + + // if the scrollbar is transient or its attributes, geometry or + // state has changed, the opacity is reset back to 100% opaque + opacity = 1.0; + + styleObject->setProperty("_q_stylepos", scrollBar->sliderPosition); + styleObject->setProperty("_q_stylemin", scrollBar->minimum); + styleObject->setProperty("_q_stylemax", scrollBar->maximum); + styleObject->setProperty("_q_stylerect", scrollBar->rect); + styleObject->setProperty("_q_stylestate", static_cast(scrollBar->state)); + styleObject->setProperty("_q_stylecontrols", static_cast(scrollBar->activeSubControls)); + + QScrollbarStyleAnimation *anim = qobject_cast(d->animation(styleObject)); + if (transient) { + if (!anim) { + anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject); + d->startAnimation(anim); + } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) { + // the scrollbar was already fading out while the + // state changed -> restart the fade out animation + anim->setCurrentTime(0); + } + } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { + d->stopAnimation(styleObject); + } + } + + QScrollbarStyleAnimation *anim = qobject_cast(d->animation(styleObject)); + if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { + // once a scrollbar was active (hovered/pressed), it retains + // the active look even if it's no longer active while fading out + if (oldActiveControls) + anim->setActive(true); + + wasActive = anim->wasActive(); + opacity = anim->currentValue(); + } + + shouldExpand = (option->activeSubControls || wasActive); + if (shouldExpand) { + if (!anim && !oldActiveControls) { + // Start expand animation only once and when entering + anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject); + d->startAnimation(anim); + } + if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) { + expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue(); + expandOffset = 5.5 * anim->currentValue() - 1; + } else { + // Keep expanded state after the animation ends, and when fading out + expandScale = maxExpandScale; + expandOffset = 4.5; + } + } + painter->setOpacity(opacity); + } + + bool transient = proxy()->styleHint(SH_ScrollBar_Transient, option, widget); bool horizontal = scrollBar->orientation == Qt::Horizontal; bool sunken = scrollBar->state & State_Sunken; @@ -2408,20 +2493,53 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption QColor arrowColor = option->palette.foreground().color(); arrowColor.setAlpha(220); + const QColor bgColor = option->palette.color(QPalette::Base); + const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128; + + if (transient) { + if (horizontal) { + rect.setY(rect.y() + 4.5 - expandOffset); + scrollBarSlider.setY(scrollBarSlider.y() + 4.5 - expandOffset); + scrollBarGroove.setY(scrollBarGroove.y() + 4.5 - expandOffset); + + rect.setHeight(rect.height() * expandScale); + scrollBarGroove.setHeight(scrollBarGroove.height() * expandScale); + } else { + rect.setX(rect.x() + 4.5 - expandOffset); + scrollBarSlider.setX(scrollBarSlider.x() + 4.5 - expandOffset); + scrollBarGroove.setX(scrollBarGroove.x() + 4.5 - expandOffset); + + rect.setWidth(rect.width() * expandScale); + scrollBarGroove.setWidth(scrollBarGroove.width() * expandScale); + } + } + // Paint groove - if (scrollBar->subControls & SC_ScrollBarGroove) { + if ((!transient || scrollBar->activeSubControls || wasActive) && scrollBar->subControls & SC_ScrollBarGroove) { QLinearGradient gradient(rect.center().x(), rect.top(), rect.center().x(), rect.bottom()); if (!horizontal) gradient = QLinearGradient(rect.left(), rect.center().y(), rect.right(), rect.center().y()); - gradient.setColorAt(0, buttonColor.darker(107)); - gradient.setColorAt(0.1, buttonColor.darker(105)); - gradient.setColorAt(0.9, buttonColor.darker(105)); - gradient.setColorAt(1, buttonColor.darker(107)); + if (!transient || !isDarkBg) { + gradient.setColorAt(0, buttonColor.darker(107)); + gradient.setColorAt(0.1, buttonColor.darker(105)); + gradient.setColorAt(0.9, buttonColor.darker(105)); + gradient.setColorAt(1, buttonColor.darker(107)); + } else { + gradient.setColorAt(0, bgColor.lighter(157)); + gradient.setColorAt(0.1, bgColor.lighter(155)); + gradient.setColorAt(0.9, bgColor.lighter(155)); + gradient.setColorAt(1, bgColor.lighter(157)); + } - painter->fillRect(option->rect, gradient); + painter->save(); + if (transient) + painter->setOpacity(0.8); + painter->fillRect(rect, gradient); painter->setPen(Qt::NoPen); + if (transient) + painter->setOpacity(0.4); painter->setPen(alphaOutline); if (horizontal) painter->drawLine(rect.topLeft(), rect.topRight()); @@ -2432,7 +2550,6 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption subtleEdge.setAlpha(40); painter->setPen(Qt::NoPen); painter->setBrush(Qt::NoBrush); - painter->save(); painter->setClipRect(scrollBarGroove.adjusted(1, 0, -1, -3)); painter->drawRect(scrollBarGroove.adjusted(1, 0, -1, -1)); painter->restore(); @@ -2456,33 +2573,45 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption // Paint slider if (scrollBar->subControls & SC_ScrollBarSlider) { - QRect pixmapRect = scrollBarSlider; - painter->setPen(QPen(alphaOutline)); - if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider) - painter->setBrush(midColor2); - else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider) - painter->setBrush(highlightedGradient); - else - painter->setBrush(gradient); + if (transient) { + QRect rect = scrollBarSlider.adjusted(horizontal ? 1 : 2, horizontal ? 2 : 1, -1, -1); + painter->setPen(Qt::NoPen); + painter->setBrush(isDarkBg ? d->lightShade() : d->darkShade()); + int r = qMin(rect.width(), rect.height()) / 2; - painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : 1, horizontal ? 1 : 0)); - - painter->setPen(d->innerContrastLine()); - painter->drawRect(scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1)); - - // Outer shadow - // painter->setPen(subtleEdge); - // if (horizontal) { - //// painter->drawLine(scrollBarSlider.topLeft() + QPoint(-2, 0), scrollBarSlider.bottomLeft() + QPoint(2, 0)); - //// painter->drawLine(scrollBarSlider.topRight() + QPoint(-2, 0), scrollBarSlider.bottomRight() + QPoint(2, 0)); - // } else { - //// painter->drawLine(pixmapRect.topLeft() + QPoint(0, -2), pixmapRect.bottomLeft() + QPoint(0, -2)); - //// painter->drawLine(pixmapRect.topRight() + QPoint(0, 2), pixmapRect.bottomRight() + QPoint(0, 2)); - // } + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->drawRoundedRect(rect, r, r); + painter->restore(); + } else { + QRect pixmapRect = scrollBarSlider; + painter->setPen(QPen(alphaOutline)); + if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider) + painter->setBrush(midColor2); + else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider) + painter->setBrush(highlightedGradient); + else + painter->setBrush(gradient); + + painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : 1, horizontal ? 1 : 0)); + + painter->setPen(d->innerContrastLine()); + painter->drawRect(scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1)); + + // Outer shadow + // painter->setPen(subtleEdge); + // if (horizontal) { + //// painter->drawLine(scrollBarSlider.topLeft() + QPoint(-2, 0), scrollBarSlider.bottomLeft() + QPoint(2, 0)); + //// painter->drawLine(scrollBarSlider.topRight() + QPoint(-2, 0), scrollBarSlider.bottomRight() + QPoint(2, 0)); + // } else { + //// painter->drawLine(pixmapRect.topLeft() + QPoint(0, -2), pixmapRect.bottomLeft() + QPoint(0, -2)); + //// painter->drawLine(pixmapRect.topRight() + QPoint(0, 2), pixmapRect.bottomRight() + QPoint(0, 2)); + // } + } } // The SubLine (up/left) buttons - if (scrollBar->subControls & SC_ScrollBarSubLine) { + if (!transient && scrollBar->subControls & SC_ScrollBarSubLine) { if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) painter->setBrush(gradientStopColor); else if ((scrollBar->activeSubControls & SC_ScrollBarSubLine)) @@ -2523,7 +2652,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption } // The AddLine (down/right) button - if (scrollBar->subControls & SC_ScrollBarAddLine) { + if (!transient && scrollBar->subControls & SC_ScrollBarAddLine) { if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) painter->setBrush(gradientStopColor); else if ((scrollBar->activeSubControls & SC_ScrollBarAddLine)) @@ -2970,6 +3099,10 @@ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, co return 14; case PM_ScrollView_ScrollBarSpacing: return 0; + case PM_ScrollView_ScrollBarOverlap: + if (proxy()->styleHint(SH_ScrollBar_Transient, option, widget)) + return proxy()->pixelMetric(PM_ScrollBarExtent, option, widget); + return 0; default: break; } @@ -3099,6 +3232,7 @@ void QFusionStyle::polish(QWidget *widget) || (widget->inherits("QDockWidgetSeparator")) ) { widget->setAttribute(Qt::WA_Hover, true); + widget->setAttribute(Qt::WA_OpaquePaintEvent, false); } } -- cgit v1.2.3 From ba4d1547372b7f3c1d7d4ea1cbf6785cfca90755 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 7 Mar 2014 15:31:21 +0100 Subject: Logging: Remove PatternFlag::Invalid from QLoggingRule The flag is not orthogonal to the rest, and e.g. checking with flags & Invalid will fail. Rather make it explicit by comparing with 0. Change-Id: I428d5e71f5ecd05f61d543aaa78532548ef93d5a Reviewed-by: Friedemann Kleint --- src/corelib/io/qloggingregistry.cpp | 7 ++----- src/corelib/io/qloggingregistry_p.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index d79de3f0e8..7e6883fd14 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -62,7 +62,6 @@ Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry) Constructs a logging rule with default values. */ QLoggingRule::QLoggingRule() : - flags(Invalid), enabled(false) { } @@ -73,7 +72,6 @@ QLoggingRule::QLoggingRule() : */ QLoggingRule::QLoggingRule(const QStringRef &pattern, bool enabled) : messageType(-1), - flags(Invalid), enabled(enabled) { parse(pattern); @@ -147,7 +145,6 @@ void QLoggingRule::parse(const QStringRef &pattern) p = pattern; } - flags = Invalid; if (!p.contains(QLatin1Char('*'))) { flags = FullText; } else { @@ -160,7 +157,7 @@ void QLoggingRule::parse(const QStringRef &pattern) p = QStringRef(p.string(), p.position() + 1, p.length() - 1); } if (p.contains(QLatin1Char('*'))) // '*' only supported at start/end - flags = Invalid; + flags = 0; } category = p.toString(); @@ -225,7 +222,7 @@ void QLoggingSettingsParser::setContent(QTextStream &stream) bool enabled = (value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0); QLoggingRule rule(pattern, enabled); - if (rule.flags != QLoggingRule::Invalid) + if (rule.flags != 0) _rules.append(rule); else warnMsg("Ignoring malformed logging rule: '%s'", line.toUtf8().constData()); diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index 21896bb268..48804cfc2b 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -72,7 +72,6 @@ public: int pass(const QString &categoryName, QtMsgType type) const; enum PatternFlag { - Invalid = 0x0, FullText = 0x1, LeftFilter = 0x2, RightFilter = 0x4, -- cgit v1.2.3 From 53f81ac946d69bcd68a02620bf52dc42fcdcc506 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Wed, 19 Feb 2014 12:15:00 +0100 Subject: BlackBerry networking: call special select() method ... so that the socket notifiers are enabled after selecting and thus emit signals even after selecting (select() is called e.g. by the waitFor* methods). Task-number: QTBUG-36144 Change-Id: I385f288e8c42f92a9c84e53bce843e52f8094ada Reviewed-by: Kevin Krammer Reviewed-by: Rafael Roquetto Reviewed-by: Fanda Vacek Reviewed-by: Bernd Weimer Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_unix.cpp | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index b1b19528c2..6ee8b696df 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -1120,6 +1120,53 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) return qint64(r); } +#ifdef Q_OS_BLACKBERRY +int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const +{ + fd_set fds; + FD_ZERO(&fds); + FD_SET(socketDescriptor, &fds); + + int retval; + QList notifiers; + if (selectForRead) { + notifiers << readNotifier; + retval = bb_select(notifiers, socketDescriptor + 1, &fds, 0, timeout); + } else { + notifiers << writeNotifier; + retval = bb_select(notifiers, socketDescriptor + 1, 0, &fds, timeout); + } + + return retval; +} + +int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) const +{ + fd_set fdread; + FD_ZERO(&fdread); + if (checkRead) + FD_SET(socketDescriptor, &fdread); + + fd_set fdwrite; + FD_ZERO(&fdwrite); + if (checkWrite) + FD_SET(socketDescriptor, &fdwrite); + + QList notifiers; + notifiers << readNotifier << writeNotifier; + int ret = bb_select(notifiers, socketDescriptor + 1, &fdread, &fdwrite, timeout); + + if (ret <= 0) + return ret; + *selectForRead = FD_ISSET(socketDescriptor, &fdread); + *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite); + + return ret; +} + +#else // not Q_OS_BLACKBERRY: + int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const { fd_set fds; @@ -1166,5 +1213,6 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c return ret; } +#endif // Q_OS_BLACKBERRY QT_END_NAMESPACE -- cgit v1.2.3 From d9f5200fb852ae9dbe89bbc511960bfd51ecd091 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 7 Mar 2014 14:49:34 +0100 Subject: network: add support for NTLM Session Security tested manually with internal proxy. Patch-by: Jonathan Lauvernier Change-Id: Ief5b4579b3444ce70eb99637edf771d37d3971fb Reviewed-by: Peter Hartmann --- src/network/kernel/qauthenticator.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index edbbbf5a75..f7b956651f 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -981,7 +981,7 @@ public: QNtlmPhase1Block() { qstrncpy(magic, "NTLMSSP", 8); type = 1; - flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_REQUEST_TARGET; + flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM2; } // extracted @@ -1423,9 +1423,16 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas ds.setByteOrder(QDataStream::LittleEndian); QNtlmPhase3Block pb; + // set NTLMv2 + if (ch.flags & NTLMSSP_NEGOTIATE_NTLM2) + pb.flags |= NTLMSSP_NEGOTIATE_NTLM2; + + // set Always Sign + if (ch.flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) + pb.flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + bool unicode = ch.flags & NTLMSSP_NEGOTIATE_UNICODE; - pb.flags = NTLMSSP_NEGOTIATE_NTLM; if (unicode) pb.flags |= NTLMSSP_NEGOTIATE_UNICODE; else -- cgit v1.2.3 From 80151389d6835629f746b0e61865b41d81a33feb Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 20 Mar 2014 17:23:14 +0200 Subject: Android: Try to hide the sw keyboard on finishComposingText. finishComposingText is called when the composing text is finished also when the sw keyboard is hidden. Task-number: QTBUG-37631 Change-Id: I4f4e90e60ac3f89784755b591f578e07fdbfdd2a Reviewed-by: Paul Olav Tvete --- src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java index 5fdeb12c15..5e6e227c2b 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java @@ -128,7 +128,7 @@ public class QtInputConnection extends BaseInputConnection if (closing && m_inputState == InputStates.Hiding) return; - if (closing && m_inputState == InputStates.FinishComposing && m_view.getActivityDelegate().isSoftwareKeyboardVisible()) { + if (closing && m_view.getActivityDelegate().isSoftwareKeyboardVisible()) { m_view.postDelayed(new HideKeyboardRunnable(this), 100); m_inputState = InputStates.Hiding; } else { -- cgit v1.2.3 From 23595107cd2366a86cf968578ddb17b827c7a596 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Tue, 4 Mar 2014 17:52:09 +0100 Subject: Respect scrollbar position setting on Mac This was a regression from Qt 4.7. [ChangeLog][Widgets][QScrollArea] Respect scrollbar setting for click-position on Mac. Task-number: QTBUG-36314 Change-Id: I8bdb1aec9b308b0907f5db29d3519998bc843c18 Reviewed-by: J-P Nurmi --- src/widgets/styles/qmacstyle_mac.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index d4b937ec03..c4e77425bd 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -2517,12 +2517,12 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w ret = 100; break; case SH_ScrollBar_LeftClickAbsolutePosition: { + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + bool result = [defaults boolForKey:@"AppleScrollerPagingBehavior"]; if(QApplication::keyboardModifiers() & Qt::AltModifier) - ret = false; - //ret = !qt_scrollbar_jump_to_pos; + ret = !result; else - ret = true; - //ret = qt_scrollbar_jump_to_pos; + ret = result; break; } case SH_TabBar_PreferNoArrows: ret = true; -- cgit v1.2.3 From 7a08f714a582b2dd1dbdcbc4c20cebc3d7536fe1 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Wed, 19 Mar 2014 14:18:43 +0200 Subject: Fix bundled HarfBuzz-NG build on Mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2229c77b4951c2ba9b445286cb94a2a86e345c34 Reviewed-by: Tor Arne Vestbø --- src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro | 8 ++++++++ src/3rdparty/harfbuzz-ng/src/hb-coretext.h | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro index d65520927b..7d997d7d8b 100644 --- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro +++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro @@ -121,6 +121,14 @@ mac { HEADERS += \ $$PWD/src/hb-coretext.h + + ios: \ + # On iOS CoreText and CoreGraphics are stand-alone frameworks + LIBS_PRIVATE += -framework CoreText -framework CoreGraphics + else: \ + # On Mac OS they are part of the ApplicationServices umbrella framework, + # even in 10.8 where they were also made available stand-alone. + LIBS_PRIVATE += -framework ApplicationServices } TARGET = $$TARGET$$qtPlatformTargetSuffix() diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h index bcf1de7141..aa4bf69a52 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h @@ -29,7 +29,13 @@ #include "hb.h" -#include +#include +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +# include +# include +#else +# include +#endif HB_BEGIN_DECLS -- cgit v1.2.3 From 2bc7a40048ada41c59ddac0988bb2e04c227a18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 10 Mar 2014 15:16:47 +0100 Subject: Teach font database to populate families lazily Instead of requiring that QPlatformFontDatabase::populateFontDatabase() populates every single font in the system by calling registerFont(), we now allow the platform database to call registerFontFamily() instead, and then keep track of which families we've yet to fully populate in the font database. Once a property of a family is requested (such as its writing system, style, etc), the family is lazily populated by calling back to the platform database through QPlatformFontDatabase::populateFamily(), which in turn does the final call to registerFont() as before. This cuts application startup on OS X and iOS (of which the font population used to be a major limiting factor) from roughly one second to about 350ms. Task-number: QTBUG-37165 Change-Id: Ic2fc3447beb818ffe23635a5b7816ed7e70c93a7 Reviewed-by: Konstantin Ritt Reviewed-by: Erik Verbruggen Reviewed-by: Simon Hausmann --- src/gui/text/qfontdatabase.cpp | 91 ++++++++++++++++------ src/gui/text/qplatformfontdatabase.cpp | 32 +++++++- src/gui/text/qplatformfontdatabase.h | 2 + .../fontdatabases/mac/qcoretextfontdatabase.mm | 49 ++++++++---- .../fontdatabases/mac/qcoretextfontdatabase_p.h | 1 + 5 files changed, 136 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 02b9e6d25c..ae7b6c1c0d 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -317,6 +317,7 @@ struct QtFontFamily QtFontFamily(const QString &n) : + populated(false), fixedPitch(false), name(n), count(0), foundries(0) , bogusWritingSystems(false) @@ -330,6 +331,7 @@ struct QtFontFamily free(foundries); } + bool populated : 1; bool fixedPitch : 1; QString name; @@ -344,6 +346,8 @@ struct QtFontFamily bool matchesFamilyName(const QString &familyName) const; QtFontFoundry *foundry(const QString &f, bool = false); + + void ensurePopulated(); }; QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) @@ -375,6 +379,14 @@ bool QtFontFamily::matchesFamilyName(const QString &familyName) const return name.compare(familyName, Qt::CaseInsensitive) == 0 || aliases.contains(familyName, Qt::CaseInsensitive); } +void QtFontFamily::ensurePopulated() +{ + if (populated) + return; + + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamily(name); + Q_ASSERT(populated); +} class QFontDatabasePrivate { @@ -386,7 +398,14 @@ public: ~QFontDatabasePrivate() { free(); } - QtFontFamily *family(const QString &f, bool = false); + + enum FamilyRequestFlags { + RequestFamily = 0, + EnsureCreated, + EnsurePopulated + }; + + QtFontFamily *family(const QString &f, FamilyRequestFlags flags = EnsurePopulated); void free() { while (count--) delete families[count]; @@ -424,8 +443,10 @@ void QFontDatabasePrivate::invalidate() emit static_cast(QCoreApplication::instance())->fontDatabaseChanged(); } -QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) +QtFontFamily *QFontDatabasePrivate::family(const QString &f, FamilyRequestFlags flags) { + QtFontFamily *fam = 0; + int low = 0; int high = count; int pos = count / 2; @@ -439,28 +460,34 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) pos = (high + low) / 2; } if (!res) - return families[pos]; + fam = families[pos]; } - if (!create) - return 0; - if (res < 0) - pos++; + if (!fam && (flags & EnsureCreated)) { + if (res < 0) + pos++; + + // qDebug() << "adding family " << f.toLatin1() << " at " << pos << " total=" << count; + if (!(count % 8)) { + QtFontFamily **newFamilies = (QtFontFamily **) + realloc(families, + (((count+8) >> 3) << 3) * sizeof(QtFontFamily *)); + Q_CHECK_PTR(newFamilies); + families = newFamilies; + } + + QtFontFamily *family = new QtFontFamily(f); + memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *)); + families[pos] = family; + count++; - // qDebug() << "adding family " << f.toLatin1() << " at " << pos << " total=" << count; - if (!(count % 8)) { - QtFontFamily **newFamilies = (QtFontFamily **) - realloc(families, - (((count+8) >> 3) << 3) * sizeof(QtFontFamily *)); - Q_CHECK_PTR(newFamilies); - families = newFamilies; + fam = families[pos]; } - QtFontFamily *family = new QtFontFamily(f); - memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *)); - families[pos] = family; - count++; - return families[pos]; + if (fam && (flags & EnsurePopulated)) + fam->ensurePopulated(); + + return fam; } @@ -670,7 +697,7 @@ void qt_registerFont(const QString &familyName, const QString &stylename, styleKey.style = style; styleKey.weight = weight; styleKey.stretch = stretch; - QtFontFamily *f = d->family(familyName, true); + QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::EnsureCreated); f->fixedPitch = fixedPitch; for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { @@ -689,6 +716,13 @@ void qt_registerFont(const QString &familyName, const QString &stylename, integration->fontDatabase()->releaseHandle(size->handle); } size->handle = handle; + f->populated = true; +} + +void qt_registerFontFamily(const QString &familyName) +{ + // Create uninitialized/unpopulated family + privateDb()->family(familyName, QFontDatabasePrivate::EnsureCreated); } void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias) @@ -697,7 +731,7 @@ void qt_registerAliasToFontFamily(const QString &familyName, const QString &alia return; QFontDatabasePrivate *d = privateDb(); - QtFontFamily *f = d->family(familyName, false); + QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily); if (!f) return; @@ -1092,6 +1126,8 @@ static int match(int script, const QFontDef &request, if (!matchFamilyName(family_name, test.family)) continue; + test.family->ensurePopulated(); + if (family_name.isEmpty()) load(test.family->name, script); @@ -1304,6 +1340,8 @@ QList QFontDatabase::writingSystems() const QList list; for (int i = 0; i < d->count; ++i) { QtFontFamily *family = d->families[i]; + family->ensurePopulated(); + if (family->count == 0) continue; for (int x = Latin; x < WritingSystemsCount; ++x) { @@ -1367,11 +1405,14 @@ QStringList QFontDatabase::families(WritingSystem writingSystem) const QStringList flist; for (int i = 0; i < d->count; i++) { QtFontFamily *f = d->families[i]; - if (f->count == 0) + if (f->populated && f->count == 0) continue; - if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported)) - continue; - if (f->count == 1) { + if (writingSystem != Any) { + f->ensurePopulated(); + if (f->writingSystems[writingSystem] != QtFontFamily::Supported) + continue; + } + if (!f->populated || f->count == 1) { flist.append(f->name); } else { for (int j = 0; j < f->count; j++) { diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 5f277c878a..33301005c6 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -53,6 +53,7 @@ void qt_registerFont(const QString &familyname, const QString &stylename, bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *hanlde); +void qt_registerFontFamily(const QString &familyName); void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias); /*! @@ -118,7 +119,7 @@ void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void * The writing systems supported by the font are specified by the \a writingSystems argument. - \sa registerQPF2Font() + \sa registerQPF2Font(), registerFontFamily() */ void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &stylename, const QString &foundryname, QFont::Weight weight, @@ -134,6 +135,18 @@ void QPlatformFontDatabase::registerFont(const QString &familyname, const QStrin fixedPitch, writingSystems, usrPtr); } +/*! + Registers a font family with the font database. The font will be + lazily populated by a callback to populateFamily() when the font + database determines that the family needs population. + + \sa populateFamily(), registerFont() +*/ +void QPlatformFontDatabase::registerFontFamily(const QString &familyName) +{ + qt_registerFontFamily(familyName); +} + class QWritingSystemsPrivate { public: @@ -249,6 +262,11 @@ QPlatformFontDatabase::~QPlatformFontDatabase() Reimplement this function in a subclass for a convenient place to initialize the internal font database. + You may lazily populate the database by calling registerFontFamily() instead + of registerFont(), in which case you'll get a callback to populateFamily() + when the required family needs population. You then call registerFont() to + finish population of the family. + The default implementation looks in the fontDir() location and registers all QPF2 fonts. */ @@ -275,6 +293,18 @@ void QPlatformFontDatabase::populateFontDatabase() } } +/*! + This function is called whenever a lazily populated family, populated + through registerFontFamily(), needs full population. + + You are expected to fully populate the family by calling registerFont() + for each font that matches the family name. +*/ +void QPlatformFontDatabase::populateFamily(const QString &familyName) +{ + Q_UNUSED(familyName); +} + /*! This function is called whenever the font database is invalidated. diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 870480809b..b200cf0e58 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -96,6 +96,7 @@ class Q_GUI_EXPORT QPlatformFontDatabase public: virtual ~QPlatformFontDatabase(); virtual void populateFontDatabase(); + virtual void populateFamily(const QString &familyName); virtual void invalidate(); virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); @@ -125,6 +126,7 @@ public: bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *handle); + static void registerFontFamily(const QString &familyName); static void registerAliasToFontFamily(const QString &familyName, const QString &alias); }; diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index afee68ebed..1c0e888758 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -41,9 +41,11 @@ #include "qglobal.h" -#ifdef Q_OS_MACX +#if defined(Q_OS_MACX) #import #import +#elif defined(Q_OS_IOS) +#import #endif #include "qcoretextfontdatabase_p.h" @@ -176,29 +178,50 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase() { } +static CFArrayRef availableFamilyNames() +{ +#if defined(Q_OS_OSX) + return CTFontManagerCopyAvailableFontFamilyNames(); +#elif defined(Q_OS_IOS) + return (CFArrayRef) [[UIFont familyNames] retain]; +#endif +} + void QCoreTextFontDatabase::populateFontDatabase() { // The caller (QFontDB) expects the db to be populate only with system fonts, so we need // to make sure that any previously registered app fonts become invisible. removeApplicationFonts(); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + QCFType familyNames = availableFamilyNames(); + const int numberOfFamilies = CFArrayGetCount(familyNames); + for (int i = 0; i < numberOfFamilies; ++i) { + QString familyName = QCFString::toQString((CFStringRef) CFArrayGetValueAtIndex(familyNames, i)); - QCFType collection = CTFontCollectionCreateFromAvailableFonts(0); - if (! collection) - return; + // Don't populate internal fonts + if (familyName.startsWith(QLatin1Char('.')) || familyName == QStringLiteral("LastResort")) + continue; - QCFType fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); - if (! fonts) - return; + QPlatformFontDatabase::registerFontFamily(familyName); + } +} - const int numFonts = CFArrayGetCount(fonts); - for (int i = 0; i < numFonts; ++i) { - CTFontDescriptorRef font = (CTFontDescriptorRef) CFArrayGetValueAtIndex(fonts, i); - populateFromDescriptor(font); +void QCoreTextFontDatabase::populateFamily(const QString &familyName) +{ + CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(familyName)); + CTFontDescriptorRef nameOnlyDescriptor = CTFontDescriptorCreateWithAttributes(attributes); + + // A single family might match several different fonts with different styles eg. + QCFType matchingFonts = (CFArrayRef) CTFontDescriptorCreateMatchingFontDescriptors(nameOnlyDescriptor, 0); + if (!matchingFonts) { + qWarning() << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName; + return; } - [pool release]; + const int numFonts = CFArrayGetCount(matchingFonts); + for (int i = 0; i < numFonts; ++i) + populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i))); } void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index c6fc791503..c73f4a32ca 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -72,6 +72,7 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase(); + void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); -- cgit v1.2.3 From 3b8b47db6aaeb333f106cff57cc712b01d828302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 13 Feb 2014 14:14:44 +0100 Subject: Set unified toolbar height accurately. Add registerContentBorderArea() to the Cocoa native interface which allows registering multiple "unified toolbar" areas for each window. Use this function in QToolBarLayout::setGeometry() to register the area for each TopToolBarArea toolbar. Task-number: QTBUG-36700 Change-Id: I52efcc5662556bb94f25f504be3710d0491f79b9 Reviewed-by: Jake Petroules Reviewed-by: Gabriel de Dietrich Reviewed-by: Denis Dzyubenko --- .../platforms/cocoa/qcocoanativeinterface.h | 9 ++++++ .../platforms/cocoa/qcocoanativeinterface.mm | 23 +++++++++++++- src/plugins/platforms/cocoa/qcocoawindow.h | 12 +++++++ src/plugins/platforms/cocoa/qcocoawindow.mm | 37 ++++++++++++++++++++-- src/widgets/widgets/qmainwindow.cpp | 14 ++++---- src/widgets/widgets/qtoolbarlayout.cpp | 37 ++++++++++++++++++++++ src/widgets/widgets/qtoolbarlayout_p.h | 1 + 7 files changed, 121 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index bf7e85619a..efdd433d8f 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -136,10 +136,19 @@ private: // Request a unified title and toolbar look for the window. static void setContentBorderThickness(QWindow *window, int topThickness, int bottomThickness); + // Request a unified title and toolbar look for the window by registering + // an area. Multiple callers can register areas and the platform plugin + // will extend the "unified" area to cover them. + static void registerContentBorderArea(QWindow *window, quintptr identifer, int upper, int lower); + + // Enable the unified title and toolbar area. + static void enableContentBorderArea(QWindow *window, bool enable); + // Sets a NSToolbar instance for the given QWindow. The // toolbar will be attached to the native NSWindow when // that is created; static void setNSToolbar(QWindow *window, void *nsToolbar); + }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 5e57200ebc..d6a5be8d52 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -125,6 +125,10 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setEmbeddedInForeignView); if (resource.toLower() == "setcontentborderthickness") return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderThickness); + if (resource.toLower() == "registercontentborderarea") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerContentBorderArea); + if (resource.toLower() == "enablecontentborderarea") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::enableContentBorderArea); if (resource.toLower() == "setnstoolbar") return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar); @@ -287,11 +291,28 @@ void QCocoaNativeInterface::setContentBorderThickness(QWindow *window, int topTh cocoaWindow->setContentBorderThickness(topThickness, bottomThickness); } -void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar) +void QCocoaNativeInterface::registerContentBorderArea(QWindow *window, quintptr identifier, int upper, int lower) { if (!window) return; + QCocoaWindow *cocoaWindow = static_cast(window->handle()); + if (cocoaWindow) + cocoaWindow->registerContentBorderArea(identifier, upper, lower); +} + +void QCocoaNativeInterface::enableContentBorderArea(QWindow *window, bool enable) +{ + if (!window) + return; + + QCocoaWindow *cocoaWindow = static_cast(window->handle()); + if (cocoaWindow) + cocoaWindow->enableContentBorderArea(enable); +} + +void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar) +{ QCocoaIntegration::instance()->setToolbar(window, static_cast(nsToolbar)); QCocoaWindow *cocoaWindow = static_cast(window->handle()); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index fe82edd618..96df3f4c59 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -208,6 +208,8 @@ public: void registerTouch(bool enable); void setContentBorderThickness(int topThickness, int bottomThickness); + void registerContentBorderArea(quintptr identifier, int upper, int lower); + void enableContentBorderArea(bool enable); void applyContentBorderThickness(NSWindow *window); void updateNSToolbar(); @@ -282,6 +284,16 @@ public: // for QNSView QRect m_normalGeometry; Qt::WindowFlags m_oldWindowFlags; NSApplicationPresentationOptions m_presentationOptions; + + struct BorderRange { + BorderRange(int u, int l) : upper(u), lower(l) { } + int upper; + int lower; + bool operator<(BorderRange const& right) const { + return upper < right.upper; + } + }; + QHash m_contentBorderAreas; // identifer -> uppper/lower }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index d8ec144ad2..bbd5dd7311 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1540,15 +1540,46 @@ void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickne applyContentBorderThickness(m_nsWindow); } +void QCocoaWindow::registerContentBorderArea(quintptr identifier, int upper, int lower) +{ + m_contentBorderAreas.insert(identifier, BorderRange(upper, lower)); + + // Find consecutive registered border areas, starting from the top. + QList ranges = m_contentBorderAreas.values(); + std::sort(ranges.begin(), ranges.end()); + m_topContentBorderThickness = 0; + foreach (BorderRange range, ranges) { + // Is this sub-range adjacent to or overlaping the + // existing total border area range? If so merge + // it into the total range, + if (range.upper <= (m_topContentBorderThickness + 1)) + m_topContentBorderThickness = qMax(m_topContentBorderThickness, range.lower); + else + break; + } + + m_bottomContentBorderThickness = 0; // (not supported) + if (m_drawContentBorderGradient) + applyContentBorderThickness(m_nsWindow); +} + +void QCocoaWindow::enableContentBorderArea(bool enable) +{ + m_drawContentBorderGradient = enable; + applyContentBorderThickness(m_nsWindow); +} + void QCocoaWindow::applyContentBorderThickness(NSWindow *window) { if (!window) return; - if (m_drawContentBorderGradient) - [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask]; - else + if (!m_drawContentBorderGradient) { [window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask]; + return; + } + + [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask]; if (m_topContentBorderThickness > 0) { [window setContentBorderThickness:m_topContentBorderThickness forEdge:NSMaxYEdge]; diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 07db78c06c..1d0268a244 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1508,19 +1508,17 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) #ifdef Q_OS_OSX Q_D(QMainWindow); if (isWindow()) { + d->useUnifiedToolBar = set; + createWinId(); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); QPlatformNativeInterface::NativeResourceForIntegrationFunction function = - nativeInterface->nativeResourceFunctionForIntegration("setContentBorderThickness"); + nativeInterface->nativeResourceFunctionForIntegration("enableContentBorderArea"); if (!function) return; // Not Cocoa platform plugin. - createWinId(); - - d->useUnifiedToolBar = set; - - const int toolBarHeight = 50; - typedef void (*SetContentBorderThicknessFunction)(QWindow *window, int topThickness, int bottomThickness); - (reinterpret_cast(function))(window()->windowHandle(), toolBarHeight, 0); + typedef void (*EnableContentBorderAreaFunction)(QWindow *window, bool enable); + (reinterpret_cast(function))(window()->windowHandle(), set); } #endif diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp index fe919feba9..020d180778 100644 --- a/src/widgets/widgets/qtoolbarlayout.cpp +++ b/src/widgets/widgets/qtoolbarlayout.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include #include #include #include @@ -47,6 +48,9 @@ #include #include #include +#ifdef Q_OS_OSX +#include +#endif #include "qmainwindowlayout_p.h" #include "qtoolbarextension_p.h" @@ -341,6 +345,37 @@ static bool defaultWidgetAction(QToolBarItem *item) return a != 0 && a->defaultWidget() == item->widget(); } +void QToolBarLayout::updateMacBorderMetrics() +{ +#ifdef Q_OS_OSX + QToolBar *tb = qobject_cast(parentWidget()); + if (!tb) + return; + + QRect rect = geometry(); + + QMainWindow *mainWindow = qobject_cast(tb->parentWidget()); + if (!mainWindow || !mainWindow->isWindow() || !mainWindow->unifiedTitleAndToolBarOnMac()) + return; + + QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface(); + QPlatformNativeInterface::NativeResourceForIntegrationFunction function = + nativeInterface->nativeResourceFunctionForIntegration("registerContentBorderArea"); + if (!function) + return; // Not Cocoa platform plugin. + + QPoint upper = tb->mapToParent(rect.topLeft()); + QPoint lower = tb->mapToParent(rect.bottomLeft() + QPoint(0, 1)); + + typedef void (*RegisterContentBorderAreaFunction)(QWindow *window, void *identifier, int upper, int lower); + if (mainWindow->toolBarArea(tb) == Qt::TopToolBarArea) { + (reinterpret_cast(function))(tb->window()->windowHandle(), this, upper.y(), lower.y()); + } else { + (reinterpret_cast(function))(tb->window()->windowHandle(), this, 0, 0); + } +#endif +} + void QToolBarLayout::setGeometry(const QRect &rect) { QToolBar *tb = qobject_cast(parentWidget()); @@ -355,6 +390,8 @@ void QToolBarLayout::setGeometry(const QRect &rect) QLayout::setGeometry(rect); + updateMacBorderMetrics(); + bool ranOutOfSpace = false; if (!animating) ranOutOfSpace = layoutActions(rect.size()); diff --git a/src/widgets/widgets/qtoolbarlayout_p.h b/src/widgets/widgets/qtoolbarlayout_p.h index 8605a9a6ac..b250f3adee 100644 --- a/src/widgets/widgets/qtoolbarlayout_p.h +++ b/src/widgets/widgets/qtoolbarlayout_p.h @@ -111,6 +111,7 @@ public: void updateMarginAndSpacing(); bool hasExpandFlag() const; + void updateMacBorderMetrics(); public Q_SLOTS: void setExpanded(bool b); -- cgit v1.2.3 From b76612979cd4afb67a2c09d5668fbc53f3fcc64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 14 Mar 2014 15:21:13 +0100 Subject: Cocoa: Fix geometry for embedded QWindows. Report for correct geometry for QMacNativeWidget and other QWindows that are embedded in a NSView hierarchy. This also makes mapFrom/ToGlobal work. The implementation is different than for the other cases: Add a QCoocaWindow::geometry() overload and query the geometry there, instead of using a geometry change notification which sets the geometry on the QWindow. Task-number: QTBUG-36322 Change-Id: Iab5f0c96b89610c8a4b4a7de49887b0683d551dd Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.h | 1 + src/plugins/platforms/cocoa/qcocoawindow.mm | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 96df3f4c59..6e1f00eebe 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -142,6 +142,7 @@ public: ~QCocoaWindow(); void setGeometry(const QRect &rect); + QRect geometry() const; void setCocoaGeometry(const QRect &rect); void clipChildWindows(); void clipWindow(const NSRect &clipRect); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index bbd5dd7311..c7fba4eef0 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -462,6 +462,22 @@ void QCocoaWindow::setGeometry(const QRect &rectIn) setCocoaGeometry(rect); } +QRect QCocoaWindow::geometry() const +{ + // QWindows that are embedded in a NSView hiearchy may be considered + // top-level from Qt's point of view but are not from Cocoa's point + // of view. Embedded QWindows get global (screen) geometry. + if (m_contentViewIsEmbedded) { + NSPoint windowPoint = [m_contentView convertPoint:NSMakePoint(0, 0) toView:nil]; + NSPoint screenPoint = [[m_contentView window] convertBaseToScreen:windowPoint]; // ### use convertRectToScreen after 10.6 removal + QPoint position = qt_mac_flipPoint(screenPoint).toPoint(); + QSize size = qt_mac_toQRect([m_contentView bounds]).size(); + return QRect(position, size); + } + + return QPlatformWindow::geometry(); +} + void QCocoaWindow::setCocoaGeometry(const QRect &rect) { QCocoaAutoReleasePool pool; -- cgit v1.2.3 From 3d5234eb9a200752bce8fb2539efeb4d812b3b27 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 20 Mar 2014 14:02:19 +0100 Subject: REG: Android: Fix freeze when accessing assets Change 287fa94fe2f93e2857a4c15f69435c4ea14de82e created a freeze in the assets file engine because it will try locking the mutex twice. Since prepopulateCache() is only called from create(), we don't need to lock it recursively. Task-number: QTBUG-37661 Change-Id: I00d0fed132a86c1be5603484eb6ee05454da9ef0 Reviewed-by: BogDan Vatra --- src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 4968b8f188..224a8ca9f7 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -276,7 +276,6 @@ void AndroidAssetsFileEngineHandler::prepopulateCache() const Q_ASSERT(!m_hasTriedPrepopulatingCache); m_hasTriedPrepopulatingCache = true; - QMutexLocker locker(&m_assetsCacheMutext); Q_ASSERT(m_assetsCache.isEmpty()); // Failsafe: Don't read cache files that are larger than 1MB -- cgit v1.2.3 From 37ba38b33457412ba55c37cc69dd618ef21bda5b Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 25 Feb 2014 14:16:23 +0100 Subject: iOS: implement 'close keyboard' gesture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch there were no way for the user to hide the keyboard on iPhone for multi-line edit fields unless the app had a separate button added for it. And even that would be problematic since we scroll the screen (and perhaps the button) to track the cursor. This patch implements a gesture that resembles the 'hide keyboard' gesture that UIScrollView implements on iOS 7. Note that if you start the gesture inside the edit field, you will start selecting text as well. This will also cause the cursor to move and the screen to scroll. After some testing and failing, it seems like we need to live with such artifacts until we do get around to do the only sensible thing; fix up how we do text selection on touch platforms. Working around it becomes just to messy. Change-Id: I1c0d9c88ff1f5430587a49591f165b9708e5dc60 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosinputcontext.mm | 30 ++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index fff7de8170..13a0b46745 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -39,13 +39,16 @@ ** ****************************************************************************/ -#include "qiosglobal.h" #include "qiosinputcontext.h" + +#import + +#include "qiosglobal.h" #include "qioswindow.h" #include "quiview.h" #include -@interface QIOSKeyboardListener : NSObject { +@interface QIOSKeyboardListener : UIGestureRecognizer { @public QIOSInputContext *m_context; BOOL m_keyboardVisible; @@ -63,7 +66,7 @@ - (id)initWithQIOSInputContext:(QIOSInputContext *)context { - self = [super init]; + self = [super initWithTarget:self action:@selector(gestureTriggered)]; if (self) { m_context = context; m_keyboardVisible = NO; @@ -82,6 +85,14 @@ } } Q_ASSERT(m_viewController); + + // Attach 'hide keyboard' gesture to the window, but keep it disabled when the + // keyboard is not visible. Note that we never trigger the gesture the way it is intended + // since we don't want to cancel touch events and interrupt flicking etc. Instead we use + // the gesture framework more as an event filter and hide the keyboard silently. + self.enabled = NO; + self.delaysTouchesEnded = NO; + [m_viewController.view.window addGestureRecognizer:self]; } [[NSNotificationCenter defaultCenter] @@ -102,7 +113,9 @@ - (void) dealloc { + [m_viewController.view.window removeGestureRecognizer:self]; [m_viewController release]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillShowNotification" object:nil]; @@ -150,6 +163,7 @@ // Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked. m_keyboardVisibleAndDocked = YES; m_keyboardEndRect = [self getKeyboardRect:notification]; + self.enabled = YES; if (!m_duration) { m_duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16); @@ -164,6 +178,7 @@ // Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked. m_keyboardVisibleAndDocked = NO; m_keyboardEndRect = [self getKeyboardRect:notification]; + self.enabled = NO; m_context->scroll(0); } @@ -183,6 +198,15 @@ } } +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + QPointF p = fromCGPoint([[touches anyObject] locationInView:m_viewController.view]); + if (m_keyboardRect.contains(p)) + m_context->hideInputPanel(); + + [super touchesMoved:touches withEvent:event]; +} + @end QIOSInputContext::QIOSInputContext() -- cgit v1.2.3 From 68c80163949fc4c17b84c880c28b345a3a877727 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 18 Mar 2014 15:33:37 +0100 Subject: iOS: send a Qt::Key_Return when the user hits done/enter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to send key events when the user hits enter, otherwise there is no way to know when the user has 'confirmed' the text he wrote. This is on par with how it's done for the Android port. Change-Id: I585d4198de24b0d251e5e0dd2956ce81b6483f82 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/quiview_textinput.mm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm index d0088d415a..28fb23d57b 100644 --- a/src/plugins/platforms/ios/quiview_textinput.mm +++ b/src/plugins/platforms/ios/quiview_textinput.mm @@ -492,8 +492,17 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); if (!focusObject) return; - if ([text isEqualToString:@"\n"] && self.returnKeyType == UIReturnKeyDone) - [self resignFirstResponder]; + if ([text isEqualToString:@"\n"]) { + QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); + QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier); + [self sendEventToFocusObject:press]; + [self sendEventToFocusObject:release]; + + if (self.returnKeyType == UIReturnKeyDone) + [self resignFirstResponder]; + + return; + } QInputMethodEvent e; e.setCommitString(QString::fromNSString(text)); -- cgit v1.2.3 From 9b378143a8e8e309621d79ebed421f15dee0039e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 31 Oct 2013 08:14:11 +0100 Subject: Setting QT_NO_DEBUG should not remove symbols Removing symbols when defining QT_NO_DEBUG is a bad idea. In this case it means that you can't compile corelib as a release build and widgets as debug without getting an undefined symbol. Instead leave the method in the release build, but simply don't call it. Change-Id: I50426aefd62e82bccd933323aa0f67c6e5294961 Reviewed-by: Olivier Goffart Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcoreapplication.cpp | 2 -- src/corelib/kernel/qcoreapplication_p.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index bb2feee71e..6868eb6a1e 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -506,7 +506,6 @@ QThread *QCoreApplicationPrivate::mainThread() return theMainThread; } -#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD) void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver) { QThread *currentThread = QThread::currentThread(); @@ -523,7 +522,6 @@ void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver) Q_UNUSED(currentThread); Q_UNUSED(thr); } -#endif #endif // QT_NO_QOBJECT diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index c3d83112ae..d784267a65 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -116,9 +116,7 @@ public: static QThread *mainThread(); static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data); -#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD) void checkReceiverThread(QObject *receiver); -#endif void cleanupThreadData(); #endif // QT_NO_QOBJECT -- cgit v1.2.3 From 3cf7b31c4a2964ac4ad7e9e316ed364f96a793af Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 19 Mar 2014 14:47:30 +0100 Subject: Cleanup and refactor QFontconfigDatabase::fontEngine Refactors the logic to parse the font configuration from fontconfig, so that it maybe reused for custom fonts in a later patch. Also fixes a minor mistake that meant we defaulted to medium hinting, where we tried to default full hinting. Change-Id: I1e135b8b1e3faeb213aa370ea59ebde3a671273d Reviewed-by: Konstantin Ritt Reviewed-by: Pierre Rossi --- .../fontconfig/qfontconfigdatabase.cpp | 139 +++++++++++---------- 1 file changed, 74 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index a9a85f1316..5299c6780e 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -509,6 +509,74 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, return new QFontEngineMultiFontConfig(fontEngine, script); } +namespace { +QFontEngineFT::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match) +{ + switch (hintingPreference) { + case QFont::PreferNoHinting: + return QFontEngineFT::HintNone; + case QFont::PreferVerticalHinting: + return QFontEngineFT::HintLight; + case QFont::PreferFullHinting: + return QFontEngineFT::HintFull; + case QFont::PreferDefaultHinting: + break; + } + + const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); + if (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")) { + void *hintStyleResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", + QGuiApplication::primaryScreen()); + int hintStyle = int(reinterpret_cast(hintStyleResource)); + if (hintStyle > 0) + return QFontEngine::HintStyle(hintStyle - 1); + } + + int hint_style = 0; + if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) + hint_style = FC_HINT_FULL; + switch (hint_style) { + case FC_HINT_NONE: + return QFontEngineFT::HintNone; + case FC_HINT_SLIGHT: + return QFontEngineFT::HintLight; + case FC_HINT_MEDIUM: + return QFontEngineFT::HintMedium; + case FC_HINT_FULL: + return QFontEngineFT::HintFull; + default: + Q_UNREACHABLE(); + break; + } + return QFontEngineFT::HintFull; +} + +QFontEngineFT::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match) +{ + int subpixel = FC_RGBA_UNKNOWN; + FcPatternGetInteger(match, FC_RGBA, 0, &subpixel); + + switch (subpixel) { + case FC_RGBA_UNKNOWN: + case FC_RGBA_NONE: + return QFontEngineFT::Subpixel_None; + case FC_RGBA_RGB: + return QFontEngineFT::Subpixel_RGB; + case FC_RGBA_BGR: + return QFontEngineFT::Subpixel_BGR; + case FC_RGBA_VRGB: + return QFontEngineFT::Subpixel_VRGB; + case FC_RGBA_VBGR: + return QFontEngineFT::Subpixel_VBGR; + default: + Q_UNREACHABLE(); + break; + } + return QFontEngineFT::Subpixel_None; +} +} // namespace + QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) { if (!usrPtr) @@ -548,39 +616,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) FcPattern *match = FcFontMatch(0, pattern, &result); if (match) { - QFontEngineFT::HintStyle default_hint_style; - if (f.hintingPreference != QFont::PreferDefaultHinting) { - switch (f.hintingPreference) { - case QFont::PreferNoHinting: - default_hint_style = QFontEngineFT::HintNone; - break; - case QFont::PreferVerticalHinting: - default_hint_style = QFontEngineFT::HintLight; - break; - case QFont::PreferFullHinting: - default: - default_hint_style = QFontEngineFT::HintFull; - break; - } - } else { - int hint_style = 0; - if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) - hint_style = QFontEngineFT::HintFull; - switch (hint_style) { - case FC_HINT_NONE: - default_hint_style = QFontEngineFT::HintNone; - break; - case FC_HINT_SLIGHT: - default_hint_style = QFontEngineFT::HintLight; - break; - case FC_HINT_MEDIUM: - default_hint_style = QFontEngineFT::HintMedium; - break; - default: - default_hint_style = QFontEngineFT::HintFull; - break; - } - } + engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)f.hintingPreference, match)); if (antialias) { // If antialiasing is not fully disabled, fontconfig may still disable it on a font match basis. @@ -590,40 +626,13 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) antialias = fc_antialias; } - if (f.hintingPreference == QFont::PreferDefaultHinting) { - const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); - if (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")) { - void *hintStyleResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", - QGuiApplication::primaryScreen()); - int hintStyle = int(reinterpret_cast(hintStyleResource)); - if (hintStyle > 0) - default_hint_style = QFontEngine::HintStyle(hintStyle - 1); - } - } - - engine->setDefaultHintStyle(default_hint_style); - if (antialias) { - QFontEngineFT::SubpixelAntialiasingType subpixelType = QFontEngineFT::Subpixel_None; - int subpixel = FC_RGBA_NONE; - - FcPatternGetInteger(match, FC_RGBA, 0, &subpixel); - if (subpixel == FC_RGBA_UNKNOWN) - subpixel = FC_RGBA_NONE; - - switch (subpixel) { - case FC_RGBA_NONE: subpixelType = QFontEngineFT::Subpixel_None; break; - case FC_RGBA_RGB: subpixelType = QFontEngineFT::Subpixel_RGB; break; - case FC_RGBA_BGR: subpixelType = QFontEngineFT::Subpixel_BGR; break; - case FC_RGBA_VRGB: subpixelType = QFontEngineFT::Subpixel_VRGB; break; - case FC_RGBA_VBGR: subpixelType = QFontEngineFT::Subpixel_VBGR; break; - default: break; - } - - format = subpixelType == QFontEngineFT::Subpixel_None - ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32; + QFontEngineFT::SubpixelAntialiasingType subpixelType = subpixelTypeFromMatch(match); engine->subpixelType = subpixelType; + + format = (subpixelType == QFontEngineFT::Subpixel_None) + ? QFontEngineFT::Format_A8 + : QFontEngineFT::Format_A32; } else format = QFontEngineFT::Format_Mono; -- cgit v1.2.3 From 9379dd94103e4efd5be8867892f0a562c224d26d Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Wed, 19 Mar 2014 18:03:34 +0100 Subject: QNX: Fix crash in bb_select Change-Id: Ic1a414c9d89b790ed9fb9f5c989b6018de78b465 Reviewed-by: Peter Hartmann Reviewed-by: Bernd Weimer Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qcore_unix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 8d788419fb..568453ec07 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -131,10 +131,10 @@ int bb_select(QList socketNotifiers, int nfds, fd_set *fdread socketNotifiersEnabled.reserve(socketNotifiers.count()); for (int a = 0; a < socketNotifiers.count(); ++a) { if (socketNotifiers.at(a) && socketNotifiers.at(a)->isEnabled()) { - socketNotifiersEnabled[a] = true; + socketNotifiersEnabled.append(true); socketNotifiers.at(a)->setEnabled(false); } else { - socketNotifiersEnabled[a] = false; + socketNotifiersEnabled.append(false); } } -- cgit v1.2.3 From b145c1db00ee04355221f11124efffee94ee7120 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 20 Mar 2014 13:59:45 +0100 Subject: Mac theming: Set background brush for menu palette We also remove overriding the background when polishing the palette in QMacStyle. This is a leftover from pre-10.5 styling. Change-Id: Icaa6d9c864ab01783d83cc02192981136c417d24 Reviewed-by: Jens Bache-Wiig --- src/plugins/platforms/cocoa/qcocoasystemsettings.mm | 2 ++ src/widgets/styles/qmacstyle_mac.mm | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index 1c08d4bcb7..1b3b12f337 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -191,6 +191,8 @@ QHash qt_mac_createRolePalettes() pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc); } if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette) { + qc = qt_mac_colorForTheme(kThemeBrushMenuBackground); + pal.setBrush(QPalette::Background, qc); qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemActive); pal.setBrush(QPalette::ButtonText, qc); qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index c4e77425bd..b8e02cc6c1 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1917,11 +1917,6 @@ void QMacStyle::polish(QPalette &pal) qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); } - QColor pc(Qt::black); - pc = qcolorForTheme(kThemeBrushDialogBackgroundActive); - QBrush background(pc, *qt_mac_backgroundPattern); - pal.setBrush(QPalette::All, QPalette::Window, background); - pal.setBrush(QPalette::All, QPalette::Button, background); QCFString theme; const OSErr err = CopyThemeIdentifier(&theme); -- cgit v1.2.3 From 9637b5f7f0e2f946a6d9923fbf82e8614d3a5363 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 20 Mar 2014 13:59:09 +0100 Subject: Mac theming: Remove obsolete private color conversion functions Change-Id: I165eea19c8e50f981a9fa48c14f0d63c40951747 Reviewed-by: Jens Bache-Wiig --- src/plugins/platforms/cocoa/qt_mac_p.h | 2 -- src/widgets/styles/qmacstyle_mac.mm | 12 ------------ 2 files changed, 14 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h index 581157c2e1..7d38b08d84 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/cocoa/qt_mac_p.h @@ -194,8 +194,6 @@ extern QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt) QFont qfontForThemeFont(ThemeFontID themeID); -QColor qcolorForTheme(ThemeBrush brush); - QColor qcolorForThemeTextColor(ThemeTextColor themeColor); struct QMacDndAnswerRecord { diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index b8e02cc6c1..55e808e9ba 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -526,18 +526,6 @@ static QColor qcolorFromCGColor(CGColorRef cgcolor) return pc; } -static inline QColor leopardBrush(ThemeBrush brush) -{ - QCFType cgClr = 0; - HIThemeBrushCreateCGColor(brush, &cgClr); - return qcolorFromCGColor(cgClr); -} - -QColor qcolorForTheme(ThemeBrush brush) -{ - return leopardBrush(brush); -} - OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon) { QRegion *region = static_cast(inRefcon); -- cgit v1.2.3 From e7816e987ec6fc954c971bd27de29c7160659f37 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 20 Mar 2014 15:19:52 +0100 Subject: QPA: Fix QPlatformTheme::Palette enum value spelling We keep the old value for source compatibility, but it should probably be removed at some point as the QPA API is semi-public only. Change-Id: I06e4c9ca1d8bb878411ad79ef409d60ce2d29f4a Reviewed-by: Friedemann Kleint --- src/gui/kernel/qplatformtheme.h | 1 + src/plugins/platforms/cocoa/qcocoasystemsettings.mm | 2 +- src/widgets/kernel/qapplication_qpa.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 073eda8d07..a2d14be0fb 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -130,6 +130,7 @@ public: ComboBoxPalette, ItemViewPalette, MessageBoxLabelPelette, + MessageBoxLabelPalette = MessageBoxLabelPelette, TabBarPalette, LabelPalette, GroupBoxPalette, diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index 1b3b12f337..f18be8b69c 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -161,7 +161,7 @@ static QMacPaletteMap mac_widget_colors[] = { QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive), QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive), - QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive), + QMacPaletteMap(QPlatformTheme::MessageBoxLabelPalette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive), QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive), QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index 7977ae3528..2f6e8acd87 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -283,7 +283,7 @@ void QApplicationPrivate::initializeWidgetPaletteHash() setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton"); setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView"); setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPelette), "QMessageBoxLabel"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel"); setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar"); setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel"); setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox"); -- cgit v1.2.3 From 045e20b32f233a000cee09e57ee698372c066865 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 21 Mar 2014 14:18:20 +0100 Subject: Fix qdoc warnings in QMargins, QRect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iae2486e1f335679c288e05f45e2d283a7cf971c0 Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qmargins.cpp | 12 ++++++------ src/corelib/tools/qrect.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp index 088f0dc083..03993f05a9 100644 --- a/src/corelib/tools/qmargins.cpp +++ b/src/corelib/tools/qmargins.cpp @@ -312,7 +312,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QMargins &operator+=(const QMargins &margins) + \fn QMargins &QMargins::operator+=(const QMargins &margins) Add each component of \a margins to the respective component of this object and returns a reference to it. @@ -323,7 +323,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QMargins &operator-=(const QMargins &margins) + \fn QMargins &QMargins::operator-=(const QMargins &margins) Subtract each component of \a margins from the respective component of this object and returns a reference to it. @@ -334,7 +334,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QMargins &operator*=(int factor) + \fn QMargins &QMargins::operator*=(int factor) Multiplies each component of this object by \a factor and returns a reference to it. @@ -345,7 +345,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QMargins &operator*=(qreal factor) + \fn QMargins &QMargins::operator*=(qreal factor) \overload Multiplies each component of this object by \a factor @@ -357,7 +357,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QMargins &operator/=(int divisor) + \fn QMargins &QMargins::operator/=(int divisor) Divides each component of this object by \a divisor and returns a reference to it. @@ -368,7 +368,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QMargins &operator/=(qreal divisor) + \fn QMargins &QMargins::operator/=(qreal divisor) \overload diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 33e8dd23fc..33753efbda 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -1201,7 +1201,7 @@ bool QRect::intersects(const QRect &r) const */ /*! - \fn QRect QRect::operator+=(const QMargins &margins) const + \fn QRect QRect::operator+=(const QMargins &margins) Adds the \a margins to the rectangle, growing it. @@ -1221,7 +1221,7 @@ bool QRect::intersects(const QRect &r) const */ /*! - \fn QRect QRect::operator -=(const QMargins &margins) const + \fn QRect QRect::operator -=(const QMargins &margins) Returns a rectangle shrunk by the \a margins. -- cgit v1.2.3 From 523d1c54e4ff365863ae463cc30edfb2fbb15ee3 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 20 Mar 2014 12:41:13 +0100 Subject: REG: Fix compilation with old AndroidManifest.xml For apps created with Qt 5.2.1, the AndroidManifest.xml will contain a reference to android.app.splash_screen, which was removed from the application template when the splash screen functionality was fixed by 4d08d80be60af14c5daed7c6f8d37538aea6c429. To make sure existing apps still compile, we put back a dummy splash.xml so that the reference in existing manifests still work. If this splash screen was actually used for something, it will no longer show up, so we also need to document that people should update their AndroidManifest.xml to the new system, but we can't inform people via mysterious compilation failures :) Task-number: QTBUG-37493 Change-Id: I6289f9b5e2c315fa6db502cbde27bd18e15f1f8d Reviewed-by: Christian Stromme --- src/android/java/res/layout/splash.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/android/java/res/layout/splash.xml (limited to 'src') diff --git a/src/android/java/res/layout/splash.xml b/src/android/java/res/layout/splash.xml new file mode 100644 index 0000000000..6875521a12 --- /dev/null +++ b/src/android/java/res/layout/splash.xml @@ -0,0 +1,2 @@ + + -- cgit v1.2.3 From 584088f2007d36658e3667df38c4e7f66fe66c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Br=C3=BCning?= Date: Fri, 21 Mar 2014 14:36:02 +0100 Subject: Initialize the picpainter State in the QAlphaPaintEngine. Patch by John Layt. Analog to how the print preview problems on windows were fixed, this is needed to correctly print e.g. web view contents. Task-number: QTBUG-36308 Task-number: QTBUG-37240 Change-Id: If4ecffde969ed221bbbeea80232f29f095fd71cd Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll Reviewed-by: John Layt --- src/printsupport/kernel/qpaintengine_alpha.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp index 298bb8d218..7d4dc18111 100644 --- a/src/printsupport/kernel/qpaintengine_alpha.cpp +++ b/src/printsupport/kernel/qpaintengine_alpha.cpp @@ -345,6 +345,7 @@ void QAlphaPaintEngine::flushAndInit(bool init) d->m_picpainter->setFont(painter()->font()); d->m_picpainter->setOpacity(painter()->opacity()); d->m_picpainter->setTransform(painter()->combinedTransform()); + *d->m_picpainter->d_func()->state = *painter()->d_func()->state; d->m_picengine->syncState(); } } -- cgit v1.2.3 From efcfa0b252a96a7064dcd9b1767ff61e7875bab5 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 11 Mar 2014 22:10:05 +0100 Subject: QGuiApplication: send TouchCancel when touch is interrupted by popup QQuickWindow depends on maintaining state of known touch points between events, so it needs to be notified when it will not be receiving the corresponding release event for one or more. This temporary fix needs to be reverted when we have a proper event forwarding solution. Task-number: QTBUG-37371 Change-Id: I5dc40af6feac425be8103c1586f8ebe3a6aad20d Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qguiapplication.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index c6376b2647..a19eebfb7c 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2294,6 +2294,18 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To if (w->d_func()->blockedByModalWindow) { // a modal window is blocking this window, don't allow touch events through + + // QTBUG-37371 temporary fix; TODO: revisit in 5.4 when we have a forwarding solution + if (eventType == QEvent::TouchEnd) { + // but don't leave dangling state: e.g. + // QQuickWindowPrivate::itemForTouchPointId needs to be cleared. + QTouchEvent touchEvent(QEvent::TouchCancel, + e->device, + e->modifiers); + touchEvent.setTimestamp(e->timestamp); + touchEvent.setWindow(w); + QGuiApplication::sendSpontaneousEvent(w, &touchEvent); + } continue; } -- cgit v1.2.3 From a30676f20171f2bf7a8074b21be2688fcc239b14 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Fri, 21 Mar 2014 10:47:29 +0200 Subject: Fix crash: make sure functions pointer is initialized. Change-Id: I42fd3933f33370612290e8ba252349acfae72381 Reviewed-by: Laszlo Agocs --- src/opengl/qgl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index d676abee47..de1de476b8 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2441,7 +2441,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, pixel_type, constRef.bits()); if (genMipmap && ctx->isES()) - functions->glGenerateMipmap(target); + q->functions()->glGenerateMipmap(target); #ifndef QT_NO_DEBUG GLenum error = glGetError(); if (error != GL_NO_ERROR) { -- cgit v1.2.3 From c2c136306d74b5299d85e69b8757997d469e3409 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 19 Mar 2014 15:19:53 +0100 Subject: Apply fontconfig settings to custom fonts Currently QtWebKits custom fonts does not follow the system settings on Linux. This is because they are only handled by the basic fontdatabase. This patch adds handling of custom fonts to QFontconfigDatabase. Change-Id: I676fc97840766b58cd937bb8e2c9f166f30c8a6e Reviewed-by: Pierre Rossi --- .../fontdatabases/basic/qbasicfontdatabase.cpp | 1 + .../fontconfig/qfontconfigdatabase.cpp | 50 ++++++++++++++++++++++ .../fontconfig/qfontconfigdatabase_p.h | 1 + 3 files changed, 52 insertions(+) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index 1ed5ede3e8..88814151b6 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -170,6 +170,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pi { QFontDef fontDef; fontDef.pixelSize = pixelSize; + fontDef.hintingPreference = hintingPreference; QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); if (!fe->initFromData(fontData)) { diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 5299c6780e..1a31400ea5 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -650,6 +650,56 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) return engine; } +QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + QFontEngineFT *engine = static_cast(QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); + QFontDef fontDef = engine->fontDef; + + QFontEngineFT::GlyphFormat format; + // try and get the pattern + FcPattern *pattern = FcPatternCreate(); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fontDef.family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + FcResult result; + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcPattern *match = FcFontMatch(0, pattern, &result); + if (match) { + engine->setDefaultHintStyle(defaultHintStyleFromMatch(hintingPreference, match)); + + FcBool fc_antialias; + if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) != FcResultMatch) + fc_antialias = true; + engine->antialias = fc_antialias; + + if (engine->antialias) { + QFontEngineFT::SubpixelAntialiasingType subpixelType = subpixelTypeFromMatch(match); + engine->subpixelType = subpixelType; + + format = subpixelType == QFontEngineFT::Subpixel_None + ? QFontEngineFT::Format_A8 + : QFontEngineFT::Format_A32; + } else + format = QFontEngineFT::Format_Mono; + FcPatternDestroy(match); + } else + format = QFontEngineFT::Format_A8; + + FcPatternDestroy(pattern); + + engine->defaultFormat = format; + engine->glyphFormat = format; + + return engine; +} + QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const { QStringList fallbackFamilies; diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index 9f1fd28144..ba706dc59e 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -53,6 +53,7 @@ public: void populateFontDatabase(); QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); QString resolveFontFamilyAlias(const QString &family) const; -- cgit v1.2.3 From 21f1738a94fc8544ece04b3b1ee03a11986fe59b Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Thu, 13 Mar 2014 12:16:41 +0100 Subject: QNX: Fix sending of expose events When the window geometry is changed an expose event should only be sent if the window is visible. Change-Id: I540ea7e7e07d896495547f3f8bf81738fad3ddee Reviewed-by: Bernd Weimer Reviewed-by: Sergio Ahumada --- src/plugins/platforms/qnx/qqnxwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 95b6c904f2..f11a009bca 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -248,7 +248,8 @@ void QQnxWindow::setGeometry(const QRect &rect) setGeometryHelper(newGeometry); QWindowSystemInterface::handleGeometryChange(window(), newGeometry); - QWindowSystemInterface::handleExposeEvent(window(), newGeometry); + if (isExposed()) + QWindowSystemInterface::handleExposeEvent(window(), newGeometry); } void QQnxWindow::setGeometryHelper(const QRect &rect) -- cgit v1.2.3