Merge remote-tracking branch 'origin/stable' into dev

Conflicts:
	src/gui/image/qjpeghandler.cpp

Change-Id: I9db3acea7d5c82f5da679c8eaeb29431136665f0
This commit is contained in:
Frederik Gladhorn 2014-03-24 16:10:15 +01:00
commit 3b5c0bc078
411 changed files with 34397 additions and 21967 deletions

View File

@ -43,7 +43,7 @@
int main(int, char **)
{
cups_dest_t *d;
cupsGetDests(&d);
// CUPS 1.4 test
cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);
return 0;
}

129
configure vendored
View File

@ -671,7 +671,6 @@ CFG_LARGEFILE=auto
CFG_OPENSSL=auto
CFG_PRECOMPILE=auto
CFG_SEPARATE_DEBUG_INFO=no
CFG_SEPARATE_DEBUG_INFO_NOCOPY=no
CFG_REDUCE_EXPORTS=auto
CFG_SSE2=auto
CFG_SSE3=auto
@ -1493,9 +1492,6 @@ while [ "$#" -gt 0 ]; do
separate-debug-info)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_SEPARATE_DEBUG_INFO="$VAL"
elif [ "$VAL" = "nocopy" ] ; then
CFG_SEPARATE_DEBUG_INFO="yes"
CFG_SEPARATE_DEBUG_INFO_NOCOPY="yes"
else
UNKNOWN_OPT=yes
fi
@ -3172,7 +3168,7 @@ if [ "$XPLATFORM_MAC" = "no" -a "$CFG_DEBUG_RELEASE" = "yes" ]; then
echo
fi
if [ "$CFG_XCB" != "no" ] && [ "$CFG_XKBCOMMON" = "no" ]; then
if ( [ "$CFG_XCB" = "system" ] || [ "$CFG_XCB" = "qt" ] ) && [ "$CFG_XKBCOMMON" = "no" ]; then
echo "Error: -no-xkbcommon is not supported on XCB platform plugin."
exit 101
fi
@ -3376,9 +3372,10 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then
fi
fi
# disable GTK style support auto-detection on Mac
if [ "$XPLATFORM_MAC" = "yes" ] && [ "$CFG_QGTKSTYLE" = "auto" ]; then
CFG_QGTKSTYLE=no
# disable XCB and GTK support auto-detection on Mac
if [ "$XPLATFORM_MAC" = "yes" ]; then
[ "$CFG_XCB" = "auto" ] && CFG_XCB=no
[ "$CFG_QGTKSTYLE" = "auto" ] && CFG_QGTKSTYLE=no
fi
QMAKE_CONF_COMPILER=`getXQMakeConf QMAKE_CXX`
@ -3441,21 +3438,21 @@ if [ "$CFG_PRECOMPILE" = "auto" ]; then
fi
# auto-detect support for separate debug info in objcopy
if [ "$CFG_SEPARATE_DEBUG_INFO" != "no" ] && [ "$CFG_SHARED" = "yes" ]; then
if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then
if [ "$CFG_SHARED" = "no" ]; then
echo "ERROR: -separate-debug-info is incompatible with -static"
exit 1
fi
if [ "$CFG_DEBUG" = "no" -a "$CFG_DEBUG_RELEASE" = "no" -a "$CFG_FORCEDEBUGINFO" = "no" ]; then
echo "ERROR: -separate-debug-info needs -debug, -debug-and-release, or -force-debug-info"
exit 1
fi
TEST_OBJCOPY=`getXQMakeConf QMAKE_OBJCOPY`
COMPILER_WITH_FLAGS="$TEST_COMPILER $TEST_COMPILER_CXXFLAGS"
if "$unixtests/objcopy.test" "$COMPILER_WITH_FLAGS" "$TEST_OBJCOPY" "$OPT_VERBOSE"; then
CFG_SEPARATE_DEBUG_INFO=no
else
case "$PLATFORM" in
hpux-*)
# binutils on HP-UX is buggy; default to no.
CFG_SEPARATE_DEBUG_INFO=no
;;
*)
CFG_SEPARATE_DEBUG_INFO=yes
;;
esac
echo "ERROR: -separate-debug-info was requested but this binutils does not support it."
echo "Re-run configure with -v for more information"
exit 1
fi
fi
@ -5213,26 +5210,30 @@ if [ "$CFG_XCB" != "no" ]; then
fi
QMakeVar set QMAKE_X11_PREFIX "$QMAKE_X11_PREFIX"
if compileTest qpa/xcb "xcb" $QMAKE_CFLAGS_XCB $QMAKE_LIBS_XCB; then
if [ "$CFG_XKBCOMMON" != no ] && compileTest qpa/xcb "xcb" $QMAKE_CFLAGS_XCB $QMAKE_LIBS_XCB; then
QT_CONFIG="$QT_CONFIG xcb-plugin"
if [ "$CFG_XCB" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xcb-qt"
else
CFG_XCB="system"
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xcb >= 1.5" 2>/dev/null; then
XCB_PACKAGES="xcb xcb-shm xcb-sync xcb-xfixes xcb-randr xcb-image xcb-keysyms xcb-icccm xcb-shape"
QMAKE_CFLAGS_XCB="`$PKG_CONFIG --cflags $XCB_PACKAGES 2>/dev/null`"
QMAKE_LIBS_XCB="`$PKG_CONFIG --libs $XCB_PACKAGES 2>/dev/null`"
# for xcb-xkb tests
QMAKE_CFLAGS_XKB="`$PKG_CONFIG --cflags xcb xcb-xkb 2>/dev/null`"
QMAKE_LIBS_XKB="`$PKG_CONFIG --libs xcb xcb-xkb 2>/dev/null`"
fi
if compileTest qpa/xcb-xkb "xcb-xkb" $QMAKE_CFLAGS_XKB $QMAKE_LIBS_XKB; then
CFG_XKB=yes
else
CFG_XKB=no
# libxcb version 1.10 was the first version that enables xcb-xkb by default,
# therefore the minimal xcb-xkb version we support is 1.10
CFG_XKB=no
if $PKG_CONFIG --exists "xcb-xkb >= 1.10" 2>/dev/null; then
QMAKE_CFLAGS_XKB="`$PKG_CONFIG --cflags xcb xcb-xkb 2>/dev/null`"
QMAKE_LIBS_XKB="`$PKG_CONFIG --libs xcb xcb-xkb 2>/dev/null`"
if compileTest qpa/xcb-xkb "xcb-xkb" $QMAKE_CFLAGS_XKB $QMAKE_LIBS_XKB; then
CFG_XKB=yes
fi
fi
if [ "$CFG_XKB" = "no" ]; then
QMakeVar add DEFINES QT_NO_XKB
fi
@ -5328,52 +5329,45 @@ fi
# Detect libxkbcommon
ORIG_CFG_XKBCOMMON="$CFG_XKBCOMMON"
if [ "$CFG_XKBCOMMON" != "qt" ]; then
# currently only xcb platform plugin requires xkbcommon, for other platforms it can be set to 'no'
if [ "$CFG_XKBCOMMON" != "no" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon >= 0.2.0" 2>/dev/null; then
QMAKE_CFLAGS_XKBCOMMON="`$PKG_CONFIG --cflags xkbcommon 2>/dev/null`"
QMAKE_LIBS_XKBCOMMON="`$PKG_CONFIG --libs xkbcommon 2>/dev/null`"
QMAKE_VERSION_XKBCOMMON="`$PKG_CONFIG --modversion xkbcommon 2>/dev/null`"
# currently only xcb platform plugin supports building xkbcommon
if [ "$CFG_XCB" != "no" ]; then
if [ "$CFG_XKBCOMMON" = "auto" ] || [ "$CFG_XKBCOMMON" = "system" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon xkbcommon-x11 >= 0.4.0" 2>/dev/null; then
QMAKE_CFLAGS_XKBCOMMON="`$PKG_CONFIG --cflags xkbcommon xkbcommon-x11 2>/dev/null`"
QMAKE_LIBS_XKBCOMMON="`$PKG_CONFIG --libs xkbcommon xkbcommon-x11 2>/dev/null`"
QMakeVar set QMAKE_CFLAGS_XKBCOMMON "$QMAKE_CFLAGS_XKBCOMMON"
QMakeVar set QMAKE_LIBS_XKBCOMMON "$QMAKE_LIBS_XKBCOMMON"
QMakeVar set QMAKE_VERSION_XKBCOMMON "$QMAKE_VERSION_XKBCOMMON"
CFG_XKBCOMMON=system
else
CFG_XKBCOMMON=no
fi
if [ "$CFG_XCB" != "no" ] && [ "$CFG_XKBCOMMON" = "no" ]; then
# use the bundled version instead
CFG_XKBCOMMON=qt
fi
fi
fi
if [ "$CFG_XKBCOMMON" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xkbcommon-qt"
# detect XKB config root
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkeyboard-config" 2> /dev/null; then
CFG_XKB_CONFIG_ROOT="`$PKG_CONFIG --variable=xkb_base xkeyboard-config`"
else
# search for xkb configs in most probable locations
if [ -d "/usr/share/X11/xkb" ]; then
# Linux
CFG_XKB_CONFIG_ROOT="/usr/share/X11/xkb"
elif [ -d "/usr/local/share/X11/xkb" ]; then
# BSD UNIX
CFG_XKB_CONFIG_ROOT="/usr/local/share/X11/xkb"
if [ "$CFG_XKBCOMMON" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xkbcommon-qt"
# detect XKB config root
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkeyboard-config" 2> /dev/null; then
CFG_XKB_CONFIG_ROOT="`$PKG_CONFIG --variable=xkb_base xkeyboard-config`"
else
# search for xkb configs in most probable locations
if [ -d "/usr/share/X11/xkb" ]; then
# Linux
CFG_XKB_CONFIG_ROOT="/usr/share/X11/xkb"
elif [ -d "/usr/local/share/X11/xkb" ]; then
# BSD UNIX
CFG_XKB_CONFIG_ROOT="/usr/local/share/X11/xkb"
fi
fi
fi
QMakeVar set QMAKE_XKB_CONFIG_ROOT "$CFG_XKB_CONFIG_ROOT"
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
CFG_XKB_CONFIG_ROOT="not found"
fi
fi
QMakeVar set QMAKE_XKB_CONFIG_ROOT "$CFG_XKB_CONFIG_ROOT"
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
CFG_XKB_CONFIG_ROOT="not found"
fi
elif [ "$CFG_XKBCOMMON" = "no" ]; then
QMakeVar add DEFINES QT_NO_XKBCOMMON
else
CFG_XKBCOMMON=no
fi
# EGL Support
@ -5411,7 +5405,7 @@ if [ "$CFG_EGL" != "no" ]; then
fi
if [ "$CFG_EGLFS" != "no" ]; then
if [ "$XPLATFORM_QNX" = "no" ]; then
if [ "$XPLATFORM_QNX" = "no" ] && [ "$CFG_OPENGL" != "no" ]; then
CFG_EGLFS="$CFG_EGL"
else
CFG_EGLFS="no"
@ -5842,13 +5836,8 @@ fi
[ "$CFG_STRIP" = "no" ] && QMAKE_CONFIG="$QMAKE_CONFIG nostrip"
[ "$CFG_PRECOMPILE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG precompile_header"
if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then
QMakeVar add QMAKE_CFLAGS -g
QMakeVar add QMAKE_CXXFLAGS -g
QT_CONFIG="$QT_CONFIG separate_debug_info"
fi
if [ "$CFG_SEPARATE_DEBUG_INFO_NOCOPY" = "yes" ] ; then
QT_CONFIG="$QT_CONFIG separate_debug_info_nocopy"
fi
[ "$CFG_SSE2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse2"
[ "$CFG_SSE3" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse3"
[ "$CFG_SSSE3" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG ssse3"
@ -6852,7 +6841,7 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo
fi
if [ "$ORIG_CFG_XKBCOMMON" != qt ] && [ "$CFG_XKBCOMMON" = qt ]; then
echo "NOTE: libxkbcommon 0.2.0 (or higher) not found on the system, will use "
echo "NOTE: libxkbcommon and libxkbcommon-x11 0.4.0 or higher not found on the system, will use "
echo "the bundled version from 3rd party directory."
fi
if [ "$CFG_XKBCOMMON" = "qt" ] && [ "$CFG_XKB_CONFIG_ROOT" = "not found" ]; then

17
dist/changes-5.3.0 vendored
View File

@ -15,6 +15,14 @@ corresponding to tasks in the Qt Bug Tracker:
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Platform deprecation notice *
****************************************************************************
- The support for deployment on OS X 10.6 (Snow Leopard) is deprecated
in Qt 5.3, and will be removed in Qt 5.4. The platform is currently
not tested, and most likely has issues that are not fully documented.
****************************************************************************
* Library *
****************************************************************************
@ -34,3 +42,12 @@ QtGui
- Added setSwapInterval() to QSurfaceFormat. Platforms that support
setting the swap interval are now defaulting to the value of 1,
meaning vsync is enabled.
QtSql
-----
- QSqlQuery::isNull(field) now correctly returns true for "no such field".
- QSqlQuery::isNull(fieldname) is a new overload.
- QSQLITE: Empty database name now opens in-memory database.
- QSqlError: Now handles alphanumeric error codes. Used by QPSQL.
Old numeric code is deprecated.

View File

@ -130,6 +130,8 @@ Cpp.ignoredirectives += \
Q_DECLARE_SHARED \
Q_DECLARE_TR_FUNCTIONS \
Q_DECLARE_TYPEINFO \
Q_DECL_NOEXCEPT_EXPR \
QT_DEPRECATED_X \
Q_DISABLE_COPY \
Q_DUMMY_COMPARISON_OPERATOR \
Q_ENUMS \

View File

@ -156,5 +156,5 @@ int main(int argc, char **argv)
AnalogClockWindow clock;
clock.show();
app.exec();
return app.exec();
}

View File

@ -45,14 +45,101 @@
#include <QHostAddress>
#include <QStringList>
#include <QTimer>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <stdio.h>
static void usage() {
printf("Qt DNS example - performs DNS lookups\n"
"Usage: dnslookup [-t <type>] [-s nameserver] name\n\n");
static int typeFromParameter(const QString &type)
{
if (type == "a")
return QDnsLookup::A;
if (type == "aaaa")
return QDnsLookup::AAAA;
if (type == "any")
return QDnsLookup::ANY;
if (type == "cname")
return QDnsLookup::CNAME;
if (type == "mx")
return QDnsLookup::MX;
if (type == "ns")
return QDnsLookup::NS;
if (type == "ptr")
return QDnsLookup::PTR;
if (type == "srv")
return QDnsLookup::SRV;
if (type == "txt")
return QDnsLookup::TXT;
return -1;
}
//! [0]
enum CommandLineParseResult
{
CommandLineOk,
CommandLineError,
CommandLineVersionRequested,
CommandLineHelpRequested
};
CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query, QString *errorMessage)
{
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
const QCommandLineOption nameServerOption("n", "The name server to use.", "nameserver");
parser.addOption(nameServerOption);
const QCommandLineOption typeOption("t", "The lookup type.", "type");
parser.addOption(typeOption);
parser.addPositionalArgument("name", "The name to look up.");
const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption versionOption = parser.addVersionOption();
if (!parser.parse(QCoreApplication::arguments())) {
*errorMessage = parser.errorText();
return CommandLineError;
}
if (parser.isSet(versionOption))
return CommandLineVersionRequested;
if (parser.isSet(helpOption))
return CommandLineHelpRequested;
if (parser.isSet(nameServerOption)) {
const QString nameserver = parser.value(nameServerOption);
query->nameServer = QHostAddress(nameserver);
if (query->nameServer.isNull() || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
*errorMessage = "Bad nameserver address: " + nameserver;
return CommandLineError;
}
}
if (parser.isSet(typeOption)) {
const QString typeParameter = parser.value(typeOption);
const int type = typeFromParameter(typeParameter.toLower());
if (type < 0) {
*errorMessage = "Bad record type: " + typeParameter;
return CommandLineError;
}
query->type = static_cast<QDnsLookup::Type>(type);
}
const QStringList positionalArguments = parser.positionalArguments();
if (positionalArguments.isEmpty()) {
*errorMessage = "Argument 'name' missing.";
return CommandLineError;
}
if (positionalArguments.size() > 1) {
*errorMessage = "Several 'name' arguments specified.";
return CommandLineError;
}
query->name = positionalArguments.first();
return CommandLineOk;
}
//! [0]
DnsManager::DnsManager()
{
dns = new QDnsLookup(this);
@ -61,55 +148,11 @@ DnsManager::DnsManager()
void DnsManager::execute()
{
QStringList args = QCoreApplication::instance()->arguments();
args.takeFirst();
// lookup type
dns->setType(QDnsLookup::A);
if (args.size() > 1 && args.first() == "-t") {
args.takeFirst();
const QString type = args.takeFirst().toLower();
if (type == "a")
dns->setType(QDnsLookup::A);
else if (type == "aaaa")
dns->setType(QDnsLookup::AAAA);
else if (type == "any")
dns->setType(QDnsLookup::ANY);
else if (type == "cname")
dns->setType(QDnsLookup::CNAME);
else if (type == "mx")
dns->setType(QDnsLookup::MX);
else if (type == "ns")
dns->setType(QDnsLookup::NS);
else if (type == "ptr")
dns->setType(QDnsLookup::PTR);
else if (type == "srv")
dns->setType(QDnsLookup::SRV);
else if (type == "txt")
dns->setType(QDnsLookup::TXT);
else {
printf("Bad record type: %s\n", qPrintable(type));
QCoreApplication::instance()->quit();
return;
}
}
if (args.size() > 1 && args.first() == "-s") {
args.takeFirst();
const QString ns = args.takeFirst();
QHostAddress nameserver(ns);
if (nameserver.isNull() || nameserver.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
printf("Bad nameserver address: %s\n", qPrintable(ns));
QCoreApplication::instance()->quit();
return;
}
dns->setNameserver(nameserver);
}
if (args.isEmpty()) {
usage();
QCoreApplication::instance()->quit();
return;
}
dns->setName(args.takeFirst());
dns->setType(query.type);
if (!query.nameServer.isNull())
dns->setNameserver(query.nameServer);
dns->setName(query.name);
dns->lookup();
}
@ -159,7 +202,33 @@ int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
//! [1]
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCoreApplication::setApplicationName(QCoreApplication::translate("QDnsLookupExample", "DNS Lookup Example"));
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::translate("QDnsLookupExample", "An example demonstrating the class QDnsLookup."));
DnsQuery query;
QString errorMessage;
switch (parseCommandLine(parser, &query, &errorMessage)) {
case CommandLineOk:
break;
case CommandLineError:
fputs(qPrintable(errorMessage), stderr);
fputs("\n\n", stderr);
fputs(qPrintable(parser.helpText()), stderr);
return 1;
case CommandLineVersionRequested:
printf("%s %s\n", qPrintable(QCoreApplication::applicationName()),
qPrintable(QCoreApplication::applicationVersion()));
return 0;
case CommandLineHelpRequested:
parser.showHelp();
Q_UNREACHABLE();
}
//! [1]
DnsManager manager;
manager.setQuery(query);
QTimer::singleShot(0, &manager, SLOT(execute()));
return app.exec();

View File

@ -38,11 +38,21 @@
**
****************************************************************************/
#include <QObject>
#include <QDnsLookup>
#include <QHostAddress>
QT_BEGIN_NAMESPACE
class QDnsLookup;
QT_END_NAMESPACE
//! [0]
struct DnsQuery
{
DnsQuery() : type(QDnsLookup::A) {}
QDnsLookup::Type type;
QHostAddress nameServer;
QString name;
};
//! [0]
class DnsManager : public QObject
{
@ -50,6 +60,7 @@ class DnsManager : public QObject
public:
DnsManager();
void setQuery(const DnsQuery &q) { query = q; }
public slots:
void execute();
@ -57,5 +68,6 @@ public slots:
private:
QDnsLookup *dns;
DnsQuery query;
};

View File

@ -174,7 +174,7 @@ void RenderWindow::setupVertexAttribs()
void RenderWindow::render()
{
if (!m_context->makeCurrent(this)) {
qWarning("makeCurrent() failed");
emit error(tr("makeCurrent() failed"));
return;
}
@ -216,5 +216,10 @@ void RenderWindow::render()
m_context->swapBuffers(this);
m_angle += 1.0f;
QTimer::singleShot(0, this, SLOT(render()));
// Instead of 0 wait a few more milliseconds before rendering again. This is
// only here to make the UI widgets more responsive on slower machines. We
// can afford it since our rendering is so lightweight.
const int interval = 5;
QTimer::singleShot(interval, this, SLOT(render()));
}

View File

@ -275,6 +275,7 @@ void Widget::start()
addRenderWindow();
return;
}
m_surface = renderWindow;
renderWindow->setForceGLSL110(forceGLSL110);
connect(renderWindow, &RenderWindow::ready, this, &Widget::renderWindowReady);
@ -284,12 +285,8 @@ void Widget::start()
addRenderWindow();
}
void Widget::renderWindowReady()
void Widget::printFormat(const QSurfaceFormat &format)
{
QOpenGLContext *context = QOpenGLContext::currentContext();
Q_ASSERT(context);
const QSurfaceFormat format = context->format();
m_output->append(tr("OpenGL version: %1.%2").arg(format.majorVersion()).arg(format.minorVersion()));
for (size_t i = 0; i < sizeof(profiles) / sizeof(Profile); ++i)
@ -310,6 +307,21 @@ void Widget::renderWindowReady()
break;
}
m_output->append(tr("Depth buffer size: %1").arg(QString::number(format.depthBufferSize())));
m_output->append(tr("Stencil buffer size: %1").arg(QString::number(format.stencilBufferSize())));
m_output->append(tr("Samples: %1").arg(QString::number(format.samples())));
m_output->append(tr("Red buffer size: %1").arg(QString::number(format.redBufferSize())));
m_output->append(tr("Green buffer size: %1").arg(QString::number(format.greenBufferSize())));
m_output->append(tr("Blue buffer size: %1").arg(QString::number(format.blueBufferSize())));
m_output->append(tr("Alpha buffer size: %1").arg(QString::number(format.alphaBufferSize())));
m_output->append(tr("Swap interval: %1").arg(QString::number(format.swapInterval())));
}
void Widget::renderWindowReady()
{
QOpenGLContext *context = QOpenGLContext::currentContext();
Q_ASSERT(context);
QString vendor, renderer, version, glslVersion;
const GLubyte *p;
QOpenGLFunctions *f = context->functions();
@ -322,22 +334,21 @@ void Widget::renderWindowReady()
if ((p = f->glGetString(GL_SHADING_LANGUAGE_VERSION)))
glslVersion = QString::fromLatin1(reinterpret_cast<const char *>(p));
m_output->append(tr("\nVendor: %1").arg(vendor));
m_output->append(tr("*** Context information ***"));
m_output->append(tr("Vendor: %1").arg(vendor));
m_output->append(tr("Renderer: %1").arg(renderer));
m_output->append(tr("OpenGL version: %1").arg(version));
m_output->append(tr("GLSL version: %1").arg(glslVersion));
m_output->append(tr("\nDepth buffer size: %1").arg(QString::number(format.depthBufferSize())));
m_output->append(tr("Stencil buffer size: %1").arg(QString::number(format.stencilBufferSize())));
m_output->append(tr("Samples: %1").arg(QString::number(format.samples())));
m_output->append(tr("Red buffer size: %1").arg(QString::number(format.redBufferSize())));
m_output->append(tr("Green buffer size: %1").arg(QString::number(format.greenBufferSize())));
m_output->append(tr("Blue buffer size: %1").arg(QString::number(format.blueBufferSize())));
m_output->append(tr("Alpha buffer size: %1").arg(QString::number(format.alphaBufferSize())));
m_output->append(tr("Swap interval: %1").arg(QString::number(format.swapInterval())));
m_output->append(tr("\n*** QSurfaceFormat from context ***"));
printFormat(context->format());
m_output->append(tr("\n*** QSurfaceFormat from window surface ***"));
printFormat(m_surface->format());
m_output->append(tr("\n*** Qt build information ***"));
const char *gltype[] = { "Desktop", "GLES 2", "GLES 1" };
m_output->append(tr("\nQt OpenGL configuration: %1")
m_output->append(tr("Qt OpenGL configuration: %1")
.arg(QString::fromLatin1(gltype[QOpenGLContext::openGLModuleType()])));
m_output->append(tr("Qt OpenGL library handle: %1")
.arg(QString::number(qintptr(QOpenGLContext::openGLModuleHandle()), 16)));

View File

@ -46,6 +46,8 @@
QT_FORWARD_DECLARE_CLASS(QComboBox)
QT_FORWARD_DECLARE_CLASS(QTextEdit)
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
QT_FORWARD_DECLARE_CLASS(QSurfaceFormat)
QT_FORWARD_DECLARE_CLASS(QSurface)
class Widget : public QWidget
{
@ -65,6 +67,7 @@ private:
void addOptions(QLayout *layout);
void addRenderableTypes(QLayout *layout);
void addRenderWindow();
void printFormat(const QSurfaceFormat &format);
QComboBox *m_version;
QLayout *m_profiles;
@ -74,6 +77,7 @@ private:
QTextEdit *m_extensions;
QVBoxLayout *m_renderWindowLayout;
QWidget *m_renderWindowContainer;
QSurface *m_surface;
};
#endif // WIDGET_H

View File

@ -43,7 +43,6 @@
#include <QMouseEvent>
#include <math.h>
#include <locale.h>
MainWidget::MainWidget(QWidget *parent) :
QGLWidget(parent),
@ -126,9 +125,6 @@ void MainWidget::initializeGL()
//! [3]
void MainWidget::initShaders()
{
// Override system locale until shaders are compiled
setlocale(LC_NUMERIC, "C");
// Compile vertex shader
if (!program.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl"))
close();
@ -144,9 +140,6 @@ void MainWidget::initShaders()
// Bind shader pipeline for use
if (!program.bind())
close();
// Restore system locale
setlocale(LC_ALL, "");
}
//! [3]

View File

@ -118,11 +118,16 @@ bool MainWindow::save()
bool MainWindow::saveAs()
//! [11] //! [12]
{
QString fileName = QFileDialog::getSaveFileName(this);
if (fileName.isEmpty())
QFileDialog dialog(this);
dialog.setWindowModality(Qt::WindowModal);
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.exec();
QStringList files = dialog.selectedFiles();
if (files.isEmpty())
return false;
return saveFile(fileName);
return saveFile(files.at(0));
}
//! [12]

View File

@ -107,11 +107,15 @@ equals(ANDROID_TARGET_ARCH, x86) {
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -gdwarf-2 -O2
QMAKE_CFLAGS_DEBUG = -g -gdwarf-2 -fno-omit-frame-pointer
} else { # arm
QMAKE_CFLAGS_RELEASE = -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -gdwarf-2 -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
QMAKE_CFLAGS_RELEASE = -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -gdwarf-2 -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
QMAKE_CFLAGS_DEBUG = -g -gdwarf-2 -marm -O0 -fno-omit-frame-pointer
equals(ANDROID_TARGET_ARCH, armeabi): equals(NDK_TOOLCHAIN_VERSION, 4.8): \
equals(ANDROID_TARGET_ARCH, armeabi): equals(NDK_TOOLCHAIN_VERSION, 4.8) {
DEFINES += QT_OS_ANDROID_GCC_48_WORKAROUND
} else {
QMAKE_CFLAGS_RELEASE += -mthumb
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -mthumb
}
}
QMAKE_CFLAGS_SHLIB = -fPIC

View File

@ -32,8 +32,6 @@
<SplashScreen Image=\"$${WINRT_MANIFEST.logo_splash}\" />
</VisualElements>
</Application>
</Applications>
<Capabilities>$${WINRT_MANIFEST.capabilities}</Capabilities>
<Dependencies>$${WINRT_MANIFEST.dependencies}</Dependencies>
</Applications>$${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies}
</Package>
<!-- Generated by qmake using the $$[QMAKE_XSPEC] mkspec. -->

View File

@ -11,8 +11,7 @@
Description=\"$${WINRT_MANIFEST.description}\"
Publisher=\"$${WINRT_MANIFEST.publisher}\"
PublisherID=\"$${WINRT_MANIFEST.publisherid}\">
<IconPath IsRelative=\"true\" IsResource=\"false\">$${WINRT_MANIFEST.logo_medium}</IconPath>
<Capabilities>$${WINRT_MANIFEST.capabilities}</Capabilities>
<IconPath IsRelative=\"true\" IsResource=\"false\">$${WINRT_MANIFEST.logo_medium}</IconPath>$${WINRT_MANIFEST.capabilities}
<Tasks>
<DefaultTask
Name=\"_default\"

View File

@ -37,8 +37,6 @@
<v2:SplashScreen Image=\"$${WINRT_MANIFEST.logo_splash}\" />
</v2:VisualElements>
</Application>
</Applications>
<Capabilities>$${WINRT_MANIFEST.capabilities}</Capabilities>
<Dependencies>$${WINRT_MANIFEST.dependencies}</Dependencies>
</Applications>$${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies}
</Package>
<!-- Generated by qmake using the $$[QMAKE_XSPEC] mkspec. -->

View File

@ -19,7 +19,6 @@ contains(TEMPLATE, .*lib) {
unix:contains(QT_CONFIG, reduce_relocations): CONFIG += bsymbolic_functions
contains(QT_CONFIG, largefile): CONFIG += largefile
contains(QT_CONFIG, separate_debug_info): CONFIG += separate_debug_info
contains(QT_CONFIG, separate_debug_info_nocopy): CONFIG += separate_debug_info_nocopy
}
warnings_are_errors:warning_clean {

View File

@ -55,12 +55,11 @@ load(qt_common)
wince*:LIBS += $$QMAKE_LIBS_GUI
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
unix|mingw {
!isEmpty(_QMAKE_SUPER_CACHE_): \
rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*
else: \
rplbase = $$MODULE_BASE_OUTDIR
lib_replace.match = $$rplbase/lib
lib_replace.replace = $$[QT_INSTALL_LIBS/raw]
QMAKE_PRL_INSTALL_REPLACE += lib_replace
}
!isEmpty(_QMAKE_SUPER_CACHE_): \
rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*
else: \
rplbase = $$MODULE_BASE_OUTDIR
lib_replace.match = $$rplbase/lib
lib_replace.replace = $$[QT_INSTALL_LIBS/raw]
lib_replace.CONFIG = path
QMAKE_PRL_INSTALL_REPLACE += lib_replace

View File

@ -134,6 +134,28 @@ contains(INSTALLS, target) {
INSTALLS += $$tdi
}
# Install GENERATED_TESTDATA.
# Logic is copied from the TESTDATA installation, only difference being that
# INSTALL target is added with CONFIG = no_check_exist
for(file, GENERATED_TESTDATA) {
tnam = $$file
tnam ~= s,\\.\\.,dotdot,
tnam ~= s,[?*],wildcard,
tnam ~= s,[^A-Za-z0-9],_,
tdi = testdata_$$tnam
tdif = $${tdi}.files
tdip = $${tdi}.path
tdic = $${tdi}.CONFIG
$$tdif = $$file
$$tdic = no_check_exist
file = $$replace(file, ^(\\.\\./)+, )
$$tdip = $${target.path}/$$dirname(file)
INSTALLS += $$tdi
}
# TEST_HELPER_INSTALLS specifies additional test helper executables for installation.
#
# Typical usage is:

View File

@ -1,5 +1,5 @@
!separate_debug_info_nocopy:have_target:!static:!isEmpty(QMAKE_OBJCOPY) {
have_target:!static:!isEmpty(QMAKE_OBJCOPY) {
qnx {
debug_info_suffix = sym
debug_info_keep = --keep-file-symbols

View File

@ -39,8 +39,13 @@
manifest_file.input = $$WINRT_MANIFEST
load(resolve_target)
BUILD_DIR = $$dirname(QMAKE_RESOLVED_TARGET)
contains(TEMPLATE, "vc.*") {
BUILD_DIR = $$OUT_PWD
} else {
load(resolve_target)
BUILD_DIR = $$dirname(QMAKE_RESOLVED_TARGET)
}
winphone: \
manifest_file.output = $$BUILD_DIR/WMAppManifest.xml
else: contains(TEMPLATE, "vc.*"): \
@ -87,16 +92,28 @@
winphone: INDENT = "$$escape_expand(\\r\\n) "
else: INDENT = "$$escape_expand(\\r\\n) "
# Capabilities are given as a string list and may change with the configuration (network, sensors, etc.)
WINRT_MANIFEST.capabilities = $$unique(WINRT_MANIFEST.capabilities)
for(CAPABILITY, WINRT_MANIFEST.capabilities): \
MANIFEST_CAPABILITIES += " <Capability Name=\"$$CAPABILITY\" />"
WINRT_MANIFEST.capabilities = $$join(MANIFEST_CAPABILITIES, $$INDENT, $$INDENT, $$INDENT)
!isEmpty(WINRT_MANIFEST.capabilities)|winphone {
MANIFEST_CAPABILITIES += "<Capabilities>"
for(CAPABILITY, WINRT_MANIFEST.capabilities): \
MANIFEST_CAPABILITIES += " <Capability Name=\"$$CAPABILITY\" />"
MANIFEST_CAPABILITIES += "</Capabilities>"
WINRT_MANIFEST.capabilities = $$join(MANIFEST_CAPABILITIES, $$INDENT, $$INDENT)
}
# Dependencies are given as a string list. The CRT dependency is added automatically above.
WINRT_MANIFEST.dependencies = $$unique(WINRT_MANIFEST.dependencies)
for(DEPENDENCY, WINRT_MANIFEST.dependencies): \
MANIFEST_DEPENDENCIES += " <PackageDependency Name=\"$$DEPENDENCY\" />"
WINRT_MANIFEST.dependencies = $$join(MANIFEST_DEPENDENCIES, $$INDENT, $$INDENT, $$INDENT)
!isEmpty(WINRT_MANIFEST.dependencies) {
MANIFEST_DEPENDENCIES += "<Dependencies>"
for(DEPENDENCY, WINRT_MANIFEST.dependencies): \
MANIFEST_DEPENDENCIES += " <PackageDependency Name=\"$$DEPENDENCY\" />"
MANIFEST_DEPENDENCIES += "</Dependencies>"
WINRT_MANIFEST.dependencies = $$join(MANIFEST_DEPENDENCIES, $$INDENT, $$INDENT)
}
# Provide default icons where needed
isEmpty(WINRT_ASSETS_PATH): WINRT_ASSETS_PATH = $$[QT_HOST_DATA/get]/mkspecs/common/winrt_winphone/assets

View File

@ -71,6 +71,7 @@ equals(TEMPLATE, app) {
distclean.depends = xcode_distclean
QMAKE_EXTRA_TARGETS += distclean
mkpath($$OUT_PWD)|error("Aborting.")
args =
for(arg, QMAKE_ARGS): \
args += $$system_quote($$arg)

View File

@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
MSVC_VER = 8.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1400 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64

View File

@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
MSVC_VER = 9.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1500 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64

View File

@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
MSVC_VER = 10.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1600 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64

View File

@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
MSVC_VER = 11.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1700 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64

View File

@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
MSVC_VER = 12.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1800 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64

View File

@ -7,11 +7,11 @@
include(../common/winrt_winphone/qmake.conf)
QMAKE_COMPILER_DEFINES += _MSC_VER=1700
QMAKE_PLATFORM = winphone $$QMAKE_PLATFORM
DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP ARM __ARM__ __arm__ QT_NO_CURSOR
DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP ARM __ARM__ __arm__
QMAKE_LFLAGS += /MACHINE:ARM
QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib
QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib
VCPROJ_ARCH = ARM
MSVC_VER = 11.0

View File

@ -7,11 +7,11 @@
include(../common/winrt_winphone/qmake.conf)
QMAKE_COMPILER_DEFINES += _MSC_VER=1700
QMAKE_PLATFORM = winphone $$QMAKE_PLATFORM
DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP X86 __X86__ __x86__ QT_NO_CURSOR
DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP X86 __X86__ __x86__
QMAKE_LFLAGS += /MACHINE:X86
QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib
QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib
VCPROJ_ARCH = Win32
MSVC_VER = 11.0

View File

@ -10,7 +10,7 @@ message(Binary files (executables): $$[QT_INSTALL_BINS])
message(Plugins: $$[QT_INSTALL_PLUGINS])
message(Data files: $$[QT_INSTALL_DATA])
message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
message(Settings: $$[QT_INSTALL_SETTINGS])
message(Settings: $$[QT_INSTALL_CONFIGURATION])
message(Examples: $$[QT_INSTALL_EXAMPLES])
#! [0]

View File

@ -2559,6 +2559,13 @@
See also \l{infile(filename, var, val)}{infile()}.
\section2 getenv(variablename)
Returns the value of the environment variable \c variablename.
This is mostly equivalent to the \c $$(variablename) syntax.
The \c getenv function, however, supports environment variables with
parentheses in their name.
\section2 join(variablename, glue, before, after)
Joins the value of \c variablename with \c glue. If this value is

View File

@ -416,8 +416,9 @@ void NmakeMakefileGenerator::init()
}
if (project->isActiveConfig("debug_info")) {
QString pdbfile = project->first("DESTDIR") + project->first("TARGET") + version + ".pdb";
project->values("QMAKE_CFLAGS").append("/Fd" + pdbfile);
project->values("QMAKE_CXXFLAGS").append("/Fd" + pdbfile);
QString escapedPdbFile = escapeFilePath(pdbfile);
project->values("QMAKE_CFLAGS").append("/Fd" + escapedPdbFile);
project->values("QMAKE_CXXFLAGS").append("/Fd" + escapedPdbFile);
project->values("QMAKE_DISTCLEAN").append(pdbfile);
}
if (project->isActiveConfig("debug")) {

View File

@ -99,7 +99,7 @@ enum ExpandFunc {
E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE,
E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS,
E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH,
E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE
E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE, E_GETENV
};
enum TestFunc {
@ -156,6 +156,7 @@ void QMakeEvaluator::initFunctionStatics()
{ "shell_path", E_SHELL_PATH },
{ "system_quote", E_SYSTEM_QUOTE },
{ "shell_quote", E_SHELL_QUOTE },
{ "getenv", E_GETENV },
};
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
statics.expands.insert(ProKey(expandInits[i].name), expandInits[i].func);
@ -1090,6 +1091,15 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
}
break;
case E_GETENV:
if (args.count() != 1) {
evalError(fL1S("getenv(arg) requires one argument."));
} else {
const ProString &var = args.at(0);
const ProString &val = ProString(m_option->getEnv(var.toQString(m_tmp1)));
ret << val;
}
break;
default:
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
break;

View File

@ -1137,57 +1137,9 @@ void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLv
}
}
void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
template<typename T>
static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data)
{
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
gl::Buffer *indexBuffer = elementArrayBuffer;
BufferStorage *storage = indexBuffer->getStorage();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
{
delete mLineLoopIB;
mLineLoopIB = NULL;
ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
}
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 0);
if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
{
ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
return gl::error(GL_OUT_OF_MEMORY);
}
const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
{
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
void* mappedMemory = NULL;
unsigned int offset;
if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
unsigned int indexBufferOffset = offset;
switch (type)
{
case GL_NONE: // Non-indexed draw
@ -1220,79 +1172,11 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
break;
default: UNREACHABLE();
}
if (!mLineLoopIB->unmapBuffer())
{
ERR("Could not unmap index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
{
IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
mAppliedIBSerial = mLineLoopIB->getSerial();
mAppliedStorageIBSerial = 0;
mAppliedIBOffset = indexBufferOffset;
}
mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
}
void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
template<typename T>
static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data)
{
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
gl::Buffer *indexBuffer = elementArrayBuffer;
BufferStorage *storage = indexBuffer->getStorage();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
if (!mTriangleFanIB)
{
mTriangleFanIB = new StreamingIndexBufferInterface(this);
if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
{
delete mTriangleFanIB;
mTriangleFanIB = NULL;
ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
}
}
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 3);
const unsigned int numTris = count - 2;
if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
{
ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
return gl::error(GL_OUT_OF_MEMORY);
}
const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
{
ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
}
void* mappedMemory = NULL;
unsigned int offset;
if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
}
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
unsigned int indexBufferOffset = offset;
switch (type)
{
case GL_NONE: // Non-indexed draw
@ -1329,6 +1213,141 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
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
if (type != GL_NONE && elementArrayBuffer)
{
gl::Buffer *indexBuffer = elementArrayBuffer;
BufferStorage *storage = indexBuffer->getStorage();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(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, indexType))
{
delete mLineLoopIB;
mLineLoopIB = NULL;
ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
}
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 0);
if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
{
ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
return gl::error(GL_OUT_OF_MEMORY);
}
const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(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);
}
void* mappedMemory = NULL;
unsigned int offset;
if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
if (indexType == GL_UNSIGNED_SHORT)
fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
else
fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory));
unsigned int indexBufferOffset = offset;
if (!mLineLoopIB->unmapBuffer())
{
ERR("Could not unmap index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
{
IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
mAppliedIBSerial = mLineLoopIB->getSerial();
mAppliedStorageIBSerial = 0;
mAppliedIBOffset = indexBufferOffset;
}
mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
}
void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
{
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
gl::Buffer *indexBuffer = elementArrayBuffer;
BufferStorage *storage = indexBuffer->getStorage();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(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, indexType))
{
delete mTriangleFanIB;
mTriangleFanIB = NULL;
ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
}
}
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 3);
const unsigned int numTris = count - 2;
if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
{
ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
return gl::error(GL_OUT_OF_MEMORY);
}
const unsigned int spaceNeeded = (numTris * 3) * sizeof(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);
}
void* mappedMemory = NULL;
unsigned int offset;
if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
}
if (indexType == GL_UNSIGNED_SHORT)
fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
else
fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory));
unsigned int indexBufferOffset = offset;
if (!mTriangleFanIB->unmapBuffer())
{

134
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro vendored Normal file
View File

@ -0,0 +1,134 @@
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
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()

View File

@ -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 <QtCore/qglobal.h>
#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 <QtCore/qcoreapplication.h>
# define atexit qAddPostRoutine
#endif
#endif /* HB_CONFIG_H */

View File

@ -32,7 +32,6 @@
#include "hb-coretext.h"
#include "hb-face-private.hh"
#include <private/qfontengine_p.h>
#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<void *> ();
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);

View File

@ -29,7 +29,13 @@
#include "hb.h"
#include <ApplicationServices/ApplicationServices.h>
#include <TargetConditionals.h>
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
# include <CoreText/CoreText.h>
# include <CoreGraphics/CoreGraphics.h>
#else
# include <ApplicationServices/ApplicationServices.h>
#endif
HB_BEGIN_DECLS

View File

@ -1,121 +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
QT += core-private
TR_EXCLUDE += $$QT_HARFBUZZ_DIR/*
} else:contains(QT_CONFIG, system-harfbuzz) {
LIBS_PRIVATE += -lharfbuzz
}

6
src/3rdparty/harfbuzzng.pri vendored Normal file
View File

@ -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
}

View File

@ -45,14 +45,17 @@
# include <sys/types.h>
#endif
#ifdef HAVE_EDITLINE
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
#if defined(HAVE_READLINE) && HAVE_READLINE!=0
# include <readline/readline.h>
# include <readline/history.h>
#else
# undef HAVE_READLINE
#endif
#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
#if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE)
# define HAVE_READLINE 1
# include <editline/readline.h>
#endif
#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 <io.h>
#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; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
){
for(i=p2op+1; i<iOp; i++) p->aiIndent[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; j<n; j++){
memcpy(zInsert+i, ",?", 2);
i += 2;
}
memcpy(zInsert+i, ");", 3);
rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
if( rc ){
fprintf(stderr, "Error %d: %s on [%s]\n",
sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
zQuery);
goto end_data_xfer;
}
for(k=0; k<2; k++){
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
for(i=0; i<n; i++){
switch( sqlite3_column_type(pQuery, i) ){
case SQLITE_NULL: {
sqlite3_bind_null(pInsert, i+1);
break;
}
case SQLITE_INTEGER: {
sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
break;
}
case SQLITE_FLOAT: {
sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
break;
}
case SQLITE_TEXT: {
sqlite3_bind_text(pInsert, i+1,
(const char*)sqlite3_column_text(pQuery,i),
-1, SQLITE_STATIC);
break;
}
case SQLITE_BLOB: {
sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
sqlite3_column_bytes(pQuery,i),
SQLITE_STATIC);
break;
}
}
} /* End for */
rc = sqlite3_step(pInsert);
if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
sqlite3_errmsg(newDb));
}
sqlite3_reset(pInsert);
cnt++;
if( (cnt%spinRate)==0 ){
printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
fflush(stdout);
}
} /* End while */
if( rc==SQLITE_DONE ) break;
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
zTable);
rc = sqlite3_prepare_v2(p->db, 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);

File diff suppressed because it is too large Load Diff

View File

@ -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.
**
** <li>[[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.
**
** <li>[[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.
**
** <li>[[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.
**
** <li>[[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.
**
** <li>[[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.
**
** </ul>
*/
#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

View File

@ -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/*

86
src/3rdparty/xkbcommon/NEWS vendored Normal file
View File

@ -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.

View File

@ -25,27 +25,17 @@ API
While xkbcommon's API is somewhat derived from the classic XKB API as found
in <X11/extensions/XKB.h> and friends, it has been substantially reworked to
expose fewer internal details to clients. The only supported API is available
in <xkbcommon/xkbcommon.h>. 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 <xkbcommon/xkbcommon-*.h> files. Additional support is provided for
X11 (XCB) clients, in the xkbcommon-x11 library, <xkbcommon/xkbcommon-x11.h>.
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.
The maintainer is Daniel Stone, who can be reached at:
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 maintainers are Daniel Stone and Ran Benita, who can be reached at:
<daniel@fooishbar.org>
<ran234@gmail.com>
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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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 <daniel@fooishbar.org>
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#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;
}

View File

@ -26,7 +26,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
@ -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;
}

View File

@ -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

121
src/3rdparty/xkbcommon/src/keymap-priv.c vendored Normal file
View File

@ -0,0 +1,121 @@
/**
* Copyright © 2012 Intel Corporation
* Copyright © 2012 Ran Benita <ran234@gmail.com>
*
* 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 <daniel@fooishbar.org>
*/
#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++;
}
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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:

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;
}

107
src/3rdparty/xkbcommon/src/utils.c vendored Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright © 2013 Ran Benita <ran234@gmail.com>
*
* 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 <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
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

View File

@ -24,8 +24,10 @@
#ifndef UTILS_H
#define UTILS_H 1
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
@ -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 */

215
src/3rdparty/xkbcommon/src/x11/util.c vendored Normal file
View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <xcb/xkb.h>
#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

View File

@ -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;
}

View File

@ -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,6 +469,28 @@ err:
return 0;
}
XKB_EXPORT xkb_keycode_t
xkb_keymap_min_keycode(struct xkb_keymap *keymap)
{
return keymap->min_key_code;
}
XKB_EXPORT xkb_keycode_t
xkb_keymap_max_keycode(struct xkb_keymap *keymap)
{
return keymap->max_key_code;
}
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)
iter(keymap, key->keycode, data);
}
/**
* Simple boolean specifying whether or not the key should repeat.
*/
@ -525,31 +504,3 @@ xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
return key->repeats;
}
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;
}

View File

@ -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,

View File

@ -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->common.type = STMT_EXPR;
expr->common.next = NULL;
expr->op = op;
expr->value_type = type;
expr->value.child = child;
EXPR_CREATE(ExprUnary, expr, op, type);
expr->unary.child = child;
return expr;
}
ExprDef *
ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
{
ExprDef *expr = malloc(sizeof(*expr));
if (!expr)
return NULL;
EXPR_CREATE(ExprBinary, expr, op, EXPR_TYPE_UNKNOWN);
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;
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 *
ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field)
{
EXPR_CREATE(ExprFieldRef, expr, EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
expr->field_ref.element = element;
expr->field_ref.field = field;
return expr;
}
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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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;
}
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. */
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[kc].keycode = kc;
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

View File

@ -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");

View File

@ -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;

View File

@ -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 <bug-gnu-gperf@gnu.org>."
#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 <string.h>
/* 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;
}

View File

@ -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
void
scanner_error(YYLTYPE *loc, void *scanner, const char *msg);
int
_xkbcommon_lex(YYSTYPE *val, YYLTYPE *loc, void *scanner);
scanner_error(struct scanner *scanner, const char *msg);
void
scanner_warn(struct scanner *s, const char *msg);
int
_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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -47,16 +47,10 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#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__)
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)
static inline bool
is_ident(char ch)
{
return s->pos < s->len ? s->s[s->pos] : '\0';
return is_graph(ch) && ch != '\\';
}
static bool
eof(struct scanner *s)
{
return peek(s) == '\0';
}
static bool
eol(struct scanner *s)
{
return peek(s) == '\n';
}
static 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 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;
}
if (i < value.len && s[i] == '[') {
int consumed;
consumed = extract_layout_index(s + i, value.len - i, &idx);
if (consumed == -1) goto error;
i += consumed;
}
else {
idx = XKB_LAYOUT_INVALID;
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);

View File

@ -0,0 +1,145 @@
/*
* Copyright © 2012 Ran Benita <ran234@gmail.com>
*
* 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

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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,
};

View File

@ -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

View File

@ -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"

View File

@ -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 <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
/**
* @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

View File

@ -197,7 +197,7 @@ typedef uint32_t xkb_keysym_t;
* layout</em> 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 <em>shift levels</em>. 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
*/

View File

@ -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

View File

@ -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;

View File

@ -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 {
@ -127,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 {

View File

@ -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
}

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" />

View File

@ -0,0 +1,256 @@
From d7eb7ea643f00d47447d755b4a2125922d69a3b3 Mon Sep 17 00:00:00 2001
From: Andrew Knight <andrew.knight@digia.com>
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<typename T>
+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<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+template<typename T>
+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<const GLubyte*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLuint*>(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<const GLubyte*>(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<unsigned int>(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<unsigned int*>(mappedMemory);
+ if (indexType == GL_UNSIGNED_SHORT)
+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
+ else
+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(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<const GLubyte*>(indices)[i];
- }
- data[count] = static_cast<const GLubyte*>(indices)[0];
- break;
- case GL_UNSIGNED_SHORT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLushort*>(indices)[i];
- }
- data[count] = static_cast<const GLushort*>(indices)[0];
- break;
- case GL_UNSIGNED_INT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLuint*>(indices)[i];
- }
- data[count] = static_cast<const GLuint*>(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<const GLubyte*>(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<unsigned int*>(mappedMemory);
+ if (indexType == GL_UNSIGNED_SHORT)
+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
+ else
+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(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<const GLubyte*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_SHORT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_INT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
- }
- break;
- default: UNREACHABLE();
- }
if (!mTriangleFanIB->unmapBuffer())
{
--
1.8.4.msysgit.0

View File

@ -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<const char *>((*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;
}

View File

@ -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.
*/

View File

@ -86,6 +86,8 @@ private:
Median<double> controlPartElapsed;
Median<double> userPartElapsed;
int m_blockSize;
Q_DISABLE_COPY(BlockSizeManager)
};
template <typename T>

Some files were not shown because too many files have changed in this diff Show More