diff --git a/client/config.h b/client/config.h index ce89312..5b4c6ac 100644 --- a/client/config.h +++ b/client/config.h @@ -39,7 +39,7 @@ #define APP_VERSION_MAJOR 0 #define APP_VERSION_MINOR 9 -#define APP_VERSION_SUFFIX 6 +#define APP_VERSION_SUFFIX 8 //#ifdef TARGET_OSX #define ICONS ":/assets/images" diff --git a/client/encryption.cpp b/client/encryption.cpp index 02121de..b9150b8 100644 --- a/client/encryption.cpp +++ b/client/encryption.cpp @@ -187,5 +187,5 @@ void IV::Generate(QByteArray &buffer) { uint8_t* data = (uint8_t*)buffer.data(); for (int i=0; i #include #include +#include +#include #include @@ -208,22 +210,14 @@ time_t chrono::strToTime(const std::string& s) QString path::pathToSettings() { -#if QT_VERSION >= 0x050000 - QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation); -#else - QString folder = QDesktopServices::storageLocation(QDesktopServices::DataLocation); -#endif + QString folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); QString path = folder + "/" + SETTINGS_FILENAME; return path; } QString path::pathToDatabase() { -#if QT_VERSION >= 0x050000 - QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation); -#else - QString folder = QDesktopServices::storageLocation(QDesktopServices::DataLocation); -#endif + QString folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); QString path = folder + "/" + DATABASENAME; return path; } @@ -255,11 +249,7 @@ QString path::pathToDatabaseTemplate() QString path::pathToLog() { -#if QT_VERSION >= 0x050000 - QString folder = QStandardPaths::writableLocation(QStandardPaths::DataLocation); -#else - QString folder = QDesktopServices::storageLocation(QDesktopServices::DataLocation); -#endif + QString folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); return folder + "/" + LOGNAME; } diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 770ed7b..2fb3f83 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -37,7 +37,7 @@ # include "platforms/linux/autostart.h" #endif -#include +// #include #include #include @@ -121,7 +121,7 @@ void MainWindow::connectUiToDatabase() // Load recent tasks QString recent = SETTINGS.data()[KEY_RECENT_TASKS].toString(); - QStringList recentList = recent.split(";", QString::SkipEmptyParts); + QStringList recentList = recent.split(";", Qt::SkipEmptyParts); for (QString& s: recentList) { Task::Id id = s.toULongLong(); @@ -1016,7 +1016,7 @@ void MainWindow::updateData() if (saveToDb) mLogger->log("Flushing timeline to DB start"); - mCurrentTask->timeline()->flush(saveToDb, QDateTime::currentDateTimeUtc().toTime_t()); + mCurrentTask->timeline()->flush(saveToDb, QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); if (saveToDb) { mLastTimelineFlush = QDateTime::currentDateTimeUtc(); @@ -1191,9 +1191,9 @@ int MainWindow::showTrayWindow(QDialog* dlg) int w = dlg->geometry().width(); int h = dlg->geometry().height(); - QRect rec = QApplication::desktop()->screenGeometry(); - int desktopHeight = rec.height(); - int desktopWidth = rec.width(); + auto screen_size = QGuiApplication::primaryScreen()->size(); + int desktopHeight = screen_size.height(); + int desktopWidth = screen_size.width(); QRect iconRect; if (mTrayIcon) @@ -1412,7 +1412,7 @@ void MainWindow::checkForUpdates() void MainWindow::systemSleep() { //qDebug() << "System goes to sleep"; - stopTracking(TSR_Automatic, QDateTime::currentDateTimeUtc().toTime_t()); + stopTracking(TSR_Automatic, QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); } void MainWindow::systemResume() @@ -1484,11 +1484,11 @@ void MainWindow::findRequested() } //ui->mFindEdit->setVisible(false); - QTextCursor c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex, nullptr); + QTextCursor c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex); if (c.isNull()) { mFindStartIndex = 0; - c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex, nullptr); + c = ui->mNoteEdit->document()->find(pattern, mFindStartIndex); } if (!c.isNull()) { @@ -1575,7 +1575,7 @@ void MainWindow::continueOnIdle() void MainWindow::breakOnIdle(const QDateTime& stopTime) { // Stop tracking - stopTracking(TSR_Manual, stopTime.toUTC().toTime_t()); + stopTracking(TSR_Manual, stopTime.toUTC().toSecsSinceEpoch()); showTimeForSelectedTask(); } diff --git a/client/qmarkdowntextedit/CMakeLists.txt b/client/qmarkdowntextedit/CMakeLists.txt index cdf5e5e..a3af903 100644 --- a/client/qmarkdowntextedit/CMakeLists.txt +++ b/client/qmarkdowntextedit/CMakeLists.txt @@ -1,49 +1,106 @@ -cmake_minimum_required(VERSION 3.3) -project(qmarkdowntextedit) +cmake_minimum_required(VERSION 3.16) # Qt requires CMake 3.16 +project(qmarkdowntextedit LANGUAGES CXX VERSION 1.0.0) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) -find_package( Qt5Core REQUIRED ) -find_package( Qt5Widgets REQUIRED ) -find_package( Qt5Gui REQUIRED ) +# add option to disable test executable +option(QMARKDOWNTEXTEDIT_EXE "Build test executable" ON) -qt5_wrap_ui(ui_qplaintexteditsearchwidget.h qplaintexteditsearchwidget.ui) +# find qt +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) +find_package(Qt${QT_VERSION_MAJOR} OPTIONAL_COMPONENTS Quick) -set(RESOURCE_FILES - media.qrc - ) +# needed for windows +if(WIN32) + set(INTL_LDFLAGS -lintl) +endif(WIN32) -qt5_add_resources(RESOURCE_ADDED ${RESOURCE_FILES}) +# QMarkdownTextEdit library +set(RC_FILES + media.qrc +) -set(SOURCE_FILES +# Translations arent loaded so don't include them +set(TS_FILES + trans/qmarkdowntextedit_de.ts + trans/qmarkdowntextedit_ur.ts + trans/qmarkdowntextedit_zh_CN.ts +) + +set(QMARKDOWNTEXTEDIT_SOURCES + ${RC_FILES} + linenumberarea.h # We need to keep this here, otherwise the build fails markdownhighlighter.cpp - markdownhighlighter.h - main.cpp - mainwindow.cpp - mainwindow.h - mainwindow.ui qmarkdowntextedit.cpp - qmarkdowntextedit.h - qplaintexteditsearchwidget.ui + qownlanguagedata.cpp + qownlanguagedata.h qplaintexteditsearchwidget.cpp + qplaintexteditsearchwidget.ui +) +set(QMARKDOWNTEXTEDIT_HEADERS + markdownhighlighter.h + qmarkdowntextedit.h qplaintexteditsearchwidget.h +) + +add_library(qmarkdowntextedit ${QMARKDOWNTEXTEDIT_SOURCES}) +set_target_properties(qmarkdowntextedit PROPERTIES + PUBLIC_HEADER "${QMARKDOWNTEXTEDIT_HEADERS}" +) + +target_link_libraries(qmarkdowntextedit PUBLIC + Qt${QT_VERSION_MAJOR}::Widgets + ${INTL_LDFLAGS} +) + +if (Qt${QT_VERSION_MAJOR}Quick_FOUND) + target_link_libraries(qmarkdowntextedit PUBLIC Qt${QT_VERSION_MAJOR}::Quick) + + add_executable(QtQuickExample examples/qml/example.cpp examples/qml/ressources.qrc) + target_link_libraries(QtQuickExample PRIVATE Qt${QT_VERSION_MAJOR}::Quick qmarkdowntextedit) +endif() + +# QMarkdownTextEdit executable +if(QMARKDOWNTEXTEDIT_EXE) + set(SOURCE_FILES + main.cpp + mainwindow.cpp + mainwindow.h + mainwindow.ui ) -add_executable(qmarkdowntextedit ${SOURCE_FILES} ${RESOURCE_ADDED}) + add_executable(qmarkdowntextedit-exe ${SOURCE_FILES}) + set_target_properties(qmarkdowntextedit-exe PROPERTIES OUTPUT_NAME "qmarkdowntextedit") + target_link_libraries(qmarkdowntextedit-exe PRIVATE + Qt${QT_VERSION_MAJOR}::Widgets + ${INTL_LDFLAGS} + qmarkdowntextedit + ) +endif() -include_directories(${Qt5Widgets_INCLUDES}) +include(GNUInstallDirs) # Doesn't fail on windows -# We need add -DQT_WIDGETS_LIB when using QtWidgets in Qt 5. -add_definitions(${Qt5Widgets_DEFINITIONS}) +# Install the lib +install(TARGETS qmarkdowntextedit + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) -# Executables fail to build with Qt 5 in the default configuration -# without -fPIE. We add that here. -set(CMAKE_CXX_FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +# Add PkgConfig config file +configure_file(qmarkdowntextedit.pc.in ${CMAKE_BINARY_DIR}/qmarkdowntextedit.pc @ONLY) +install(FILES ${CMAKE_BINARY_DIR}/qmarkdowntextedit.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig) -# The Qt5Widgets_LIBRARIES variable also includes QtGui and QtCore -target_link_libraries(qmarkdowntextedit Qt5::Widgets) +# Install exe +if(QMARKDOWNTEXTEDIT_EXE) + install(TARGETS qmarkdowntextedit-exe DESTINATION bin) +endif() diff --git a/client/qmarkdowntextedit/LICENSE b/client/qmarkdowntextedit/LICENSE index 41f4fbb..7ffb0d8 100644 --- a/client/qmarkdowntextedit/LICENSE +++ b/client/qmarkdowntextedit/LICENSE @@ -1,5 +1,5 @@ The MIT License (MIT) -Copyright (c) 2014-2019 Patrizio Bekerle +Copyright (c) 2014-2025 Patrizio Bekerle -- 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: diff --git a/client/qmarkdowntextedit/README.md b/client/qmarkdowntextedit/README.md index b94bd77..3611c37 100644 --- a/client/qmarkdowntextedit/README.md +++ b/client/qmarkdowntextedit/README.md @@ -1,33 +1,83 @@ # [QMarkdownTextEdit](https://github.com/pbek/qmarkdowntextedit) -[![Build Status Linux/OS X](https://travis-ci.org/pbek/qmarkdowntextedit.svg?branch=develop)](https://travis-ci.org/pbek/qmarkdowntextedit) + +[![Build Status GitHub Actions](https://github.com/pbek/qmarkdowntextedit/workflows/Build/badge.svg?branch=main)](https://github.com/pbek/qmarkdowntextedit/actions) +[![Build Status Linux/OS X](https://travis-ci.org/pbek/qmarkdowntextedit.svg?branch=main)](https://travis-ci.org/pbek/qmarkdowntextedit) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/github/pbek/qmarkdowntextedit)](https://ci.appveyor.com/project/pbek/qmarkdowntextedit) -QMarkdownTextEdit is a C++ Qt [QPlainTextEdit](http://doc.qt.io/qt-5/qtextplainedit.html) widget with [markdown](https://en.wikipedia.org/wiki/Markdown) highlighting and some other goodies. +QMarkdownTextEdit is a C++ Qt [QPlainTextEdit](http://doc.qt.io/qt-5/qplaintextedit.html) widget with [markdown](https://en.wikipedia.org/wiki/Markdown) highlighting and some other goodies. -## Features -- markdown highlighting -- clickable links with `Ctrl + Click` -- block indent with `Tab` and `Shift + Tab` -- duplicate text with `Ctrl + Alt + Down` -- searching of text with `Ctrl + F` - - jump between search results with `Up` and `Down` - - close search field with `Escape` -- replacing of text with `Ctrl + R` - - you can also replace text with regular expressions or whole words -- and much more... +## Widget Features + +- Markdown highlighting +- Code syntax highlighting +- Clickable links with `Ctrl + Click` +- Block indent with `Tab` and `Shift + Tab` +- Duplicate text with `Ctrl + Alt + Down` +- Searching of text with `Ctrl + F` + - Jump between search results with `Up` and `Down` + - Close search field with `Escape` +- Replacing of text with `Ctrl + R` + - You can also replace text with regular expressions or whole words +- Line numbers (Qt >= 5.5) +- Very fast +- And much more... + +## Supported Markdown Features + +Commonmark compliance is enforced where possible however we are not fully Commonmark compliant yet. Following is a list of features/extensions supported by the highlighter. Please note that this is just a plaintext editor and as such, it only does the highlighting and not rendering of the markdown to HTML. + +| Feature | Availablity | +| --------------------------------------------------------------------------------------- | ----------------------------------------------------- | +| Bolds and Italics | Yes | +| Lists (Unordered/Orderered) | Yes | +| Links and Images
(Inline/Reference/Autolinks/E-mail) | Yes (Cannot handle nested links or complex cases yet) | +| Heading (ATX and Setext) | Yes | +| Codeblocks (indented and fenced)
Both backtick and tilde code fences are supported | Yes (Only fenced code block has syntax highlighting) | +| Inline code | Yes | +| Strikethrough | Yes | +| Underline | Yes (Optional) | +| Blockquotes | Yes | +| Table | Yes | ## Screenshot + ![Screenhot](screenshot.png) -## How to use this widget -- include [qmarkdowntextedit.pri](https://github.com/pbek/qmarkdowntextedit/blob/develop/qmarkdowntextedit.pri) +## Usage + +There are multiple ways to use this. You can use the editor directly, or you can subclass it or you can just use the highlighter. + +### Using the editor + +#### QMake + +- Include [qmarkdowntextedit.pri](https://github.com/pbek/qmarkdowntextedit/blob/main/qmarkdowntextedit.pri) to your project like this `include (qmarkdowntextedit/qmarkdowntextedit.pri)` - add a normal `QPlainTextEdit` to your UI and promote it to `QMarkdownTextEdit` (base class `QPlainTextEdit`) -## References -- [QOwnNotes - cross-platform open source plain-text file notepad](http://www.qownnotes.org) +#### CMake + +- Include [CMakeLists.txt](https://github.com/pbek/qmarkdowntextedit/blob/main/CMakeLists.txt) + to your project like this `add_subdirectory(qmarkdowntextedit)` +- add a normal `QPlainTextEdit` to your UI and promote it to `QMarkdownTextEdit` (base class `QPlainTextEdit`) + +### Using the highlighter only + +Highlighter can work with both `QPlainTextEdit` and `QTextEdit`. Example: + +```cpp +auto doc = ui->plainTextEdit->document(); +auto *highlighter = new MarkdownHighlighter(doc); +``` + +## Projects using QMarkdownTextEdit + +- [QOwnNotes](https://github.com/pbek/QOwnNotes) +- [Notes](https://github.com/nuttyartist/notes) +- [CuteMarkEd-NG](https://github.com/Waqar144/CuteMarkEd-NG) ## Disclaimer -This SOFTWARE PRODUCT is provided by THE PROVIDER "as is" and "with all faults." THE PROVIDER makes no representations or warranties of any kind concerning the safety, suitability, lack of viruses, inaccuracies, typographical errors, or other harmful components of this SOFTWARE PRODUCT. + +This SOFTWARE PRODUCT is provided by THE PROVIDER "as is" and "with all faults." THE PROVIDER makes no representations or warranties of any kind concerning the safety, suitability, lack of viruses, inaccuracies, typographical errors, or other harmful components of this SOFTWARE PRODUCT. There are inherent dangers in the use of any software, and you are solely responsible for determining whether this SOFTWARE PRODUCT is compatible with your equipment and other software installed on your equipment. You are also solely responsible for the protection of your equipment and backup of your data, and THE PROVIDER will not be liable for any damages you may suffer in connection with using, modifying, or distributing this SOFTWARE PRODUCT. diff --git a/client/qmarkdowntextedit/examples/qml/example.cpp b/client/qmarkdowntextedit/examples/qml/example.cpp new file mode 100644 index 0000000..fda2bea --- /dev/null +++ b/client/qmarkdowntextedit/examples/qml/example.cpp @@ -0,0 +1,24 @@ +#include +#include + +#include "markdownhighlighter.h" + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + qmlRegisterType("MarkdownHighlighter", 1, 0, + "MarkdownHighlighter"); + + QQmlApplicationEngine engine; + + const QUrl url(QStringLiteral("qrc:/example.qml")); + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreated, &app, + [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) QCoreApplication::exit(-1); + }, + Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/client/qmarkdowntextedit/examples/qml/example.qml b/client/qmarkdowntextedit/examples/qml/example.qml new file mode 100644 index 0000000..c375701 --- /dev/null +++ b/client/qmarkdowntextedit/examples/qml/example.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 +import QtQuick.Window 2.0 +import MarkdownHighlighter 1.0 + +Window { + id: mainwindow + width: 640 + height: 400 + visible: true + title: qsTr("QtQuick Project") + + TextEdit { + id: editor + text: "# Hello world!" + focus: true + } + + MarkdownHighlighter { + id: syntaxHighlighter + textDocument: editor.textDocument + } +} diff --git a/client/qmarkdowntextedit/examples/qml/ressources.qrc b/client/qmarkdowntextedit/examples/qml/ressources.qrc new file mode 100644 index 0000000..ac94188 --- /dev/null +++ b/client/qmarkdowntextedit/examples/qml/ressources.qrc @@ -0,0 +1,5 @@ + + + example.qml + + diff --git a/client/qmarkdowntextedit/justfile b/client/qmarkdowntextedit/justfile new file mode 100644 index 0000000..458de72 --- /dev/null +++ b/client/qmarkdowntextedit/justfile @@ -0,0 +1,22 @@ +# Use `just ` to run a recipe +# https://just.systems/man/en/ + +# By default, run the `--list` command +default: + @just --list + +# Aliases + +alias fmt := format + +# Format all files +[group('linter')] +format: + nix-shell -p treefmt libclang nodePackages.prettier shfmt nixfmt-rfc-style taplo --run treefmt + +# Add git commit hashes to the .git-blame-ignore-revs file +[group('linter')] +add-git-blame-ignore-revs: + git log --pretty=format:"%H" --grep="^lint" >> .git-blame-ignore-revs + sort .git-blame-ignore-revs | uniq > .git-blame-ignore-revs.tmp + mv .git-blame-ignore-revs.tmp .git-blame-ignore-revs diff --git a/client/qmarkdowntextedit/linenumberarea.h b/client/qmarkdowntextedit/linenumberarea.h new file mode 100644 index 0000000..58c0ef9 --- /dev/null +++ b/client/qmarkdowntextedit/linenumberarea.h @@ -0,0 +1,112 @@ +#ifndef LINENUMBERAREA_H +#define LINENUMBERAREA_H + +#include +#include +#include +#include + +#include "qmarkdowntextedit.h" + +class LineNumArea final : public QWidget { + Q_OBJECT + + public: + explicit LineNumArea(QMarkdownTextEdit *parent) + : QWidget(parent), textEdit(parent) { + Q_ASSERT(parent); + + _currentLineColor = QColor(QStringLiteral("#eef067")); + _otherLinesColor = QColor(QStringLiteral("#a6a6a6")); + setHidden(true); + + // We always use fixed font to avoid "width" issues + setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + } + + void setCurrentLineColor(QColor color) { _currentLineColor = color; } + + void setOtherLineColor(QColor color) { + _otherLinesColor = std::move(color); + } + + int lineNumAreaWidth() const { + if (!enabled) { + return 0; + } + + int digits = 2; + int max = std::max(1, textEdit->blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + +#if QT_VERSION >= 0x050B00 + int space = + 13 + textEdit->fontMetrics().horizontalAdvance(u'9') * digits; +#else + int space = + 13 + textEdit->fontMetrics().width(QLatin1Char('9')) * digits; +#endif + + return space; + } + + bool isLineNumAreaEnabled() const { return enabled; } + + void setLineNumAreaEnabled(bool e) { + enabled = e; + setHidden(!e); + } + + QSize sizeHint() const override { return {lineNumAreaWidth(), 0}; } + + protected: + void paintEvent(QPaintEvent *event) override { + QPainter painter(this); + + painter.fillRect(event->rect(), + palette().color(QPalette::Active, QPalette::Window)); + + auto block = textEdit->firstVisibleBlock(); + int blockNumber = block.blockNumber(); + qreal top = textEdit->blockBoundingGeometry(block) + .translated(textEdit->contentOffset()) + .top(); + // Maybe the top is not 0? + top += textEdit->viewportMargins().top(); + qreal bottom = top; + + const QPen currentLine = _currentLineColor; + const QPen otherLines = _otherLinesColor; + painter.setFont(font()); + + while (block.isValid() && top <= event->rect().bottom()) { + top = bottom; + bottom = top + textEdit->blockBoundingRect(block).height(); + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + + auto isCurrentLine = + textEdit->textCursor().blockNumber() == blockNumber; + painter.setPen(isCurrentLine ? currentLine : otherLines); + + painter.drawText(-5, top, sizeHint().width(), + textEdit->fontMetrics().height(), + Qt::AlignRight, number); + } + + block = block.next(); + ++blockNumber; + } + } + + private: + bool enabled = false; + QMarkdownTextEdit *textEdit; + QColor _currentLineColor; + QColor _otherLinesColor; +}; + +#endif // LINENUMBERAREA_H diff --git a/client/qmarkdowntextedit/main.cpp b/client/qmarkdowntextedit/main.cpp index e960337..c3b028d 100644 --- a/client/qmarkdowntextedit/main.cpp +++ b/client/qmarkdowntextedit/main.cpp @@ -1,41 +1,35 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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 "mainwindow.h" #include -#include -#include -int main(int argc, char *argv[]) -{ +#include "mainwindow.h" + +int main(int argc, char *argv[]) { QApplication a(argc, argv); - QString filename; - if (argc > 1) { - filename = argv[1]; - } - if (!filename.isEmpty() && !QFileInfo(filename).isReadable()) { - qWarning() << filename << "is not a readable file"; - return 1; - } - MainWindow w; w.show(); - if (!filename.isEmpty()) { - w.loadFile(filename); - } - - return a.exec(); } diff --git a/client/qmarkdowntextedit/mainwindow.cpp b/client/qmarkdowntextedit/mainwindow.cpp index be3adde..0632deb 100644 --- a/client/qmarkdowntextedit/mainwindow.cpp +++ b/client/qmarkdowntextedit/mainwindow.cpp @@ -1,14 +1,25 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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. * * mainwindow.cpp * @@ -16,103 +27,12 @@ */ #include "mainwindow.h" + #include "ui_mainwindow.h" -#include "qmarkdowntextedit.h" -#include -#include -#include -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow) -{ +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); - QToolBar *toolBar = new QToolBar; - addToolBar(toolBar); - QAction *openAction = new QAction(QIcon::fromTheme("document-open"), tr("Open...")); - openAction->setShortcut(QKeySequence::Open); - connect(openAction, &QAction::triggered, this, &MainWindow::open); - - QAction *saveAction = new QAction(QIcon::fromTheme("document-save"), tr("Save")); - saveAction->setShortcut(QKeySequence::Save); - QAction *saveAsAction = new QAction(QIcon::fromTheme("document-save-as"), tr("Save as...")); - saveAsAction->setShortcut(QKeySequence::SaveAs); - QAction *quitAction = new QAction(QIcon::fromTheme("view-close"), tr("Quit")); - quitAction->setShortcut(QKeySequence::Quit); - connect(quitAction, &QAction::triggered, this, &MainWindow::onQuit); - - m_loadedContent = ui->textEdit->toPlainText(); - - toolBar->addActions({openAction, saveAction, saveAsAction, quitAction}); } -MainWindow::~MainWindow() -{ - delete ui; -} - -void MainWindow::loadFile(const QString &filename) -{ - QFile file(filename); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Failed to open" << filename; - return; - } - - m_filename = filename; - m_loadedContent = QString::fromLocal8Bit(file.readAll()); - ui->textEdit->setPlainText(m_loadedContent); -} - -void MainWindow::saveToFile(const QString &filename) -{ - QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { - qWarning() << "Failed to open" << filename; - return; - } - - m_filename = filename; - - m_loadedContent = ui->textEdit->toPlainText(); - file.write(m_loadedContent.toLocal8Bit()); -} - -void MainWindow::open() -{ - QString filename = QFileDialog::getOpenFileName(); - if (filename.isEmpty()) { - return; - } - loadFile(filename); -} - -void MainWindow::save() -{ - if (!m_filename.isEmpty()) { - saveAs(); - return; - } - - saveToFile(m_filename); -} - -void MainWindow::saveAs() -{ - QString filename = QFileDialog::getSaveFileName(); - if (filename.isEmpty()) { - return; - } - - saveToFile(filename); -} - -void MainWindow::onQuit() -{ - if (ui->textEdit->toPlainText() != m_loadedContent) { - if (QMessageBox::question(this, tr("Not saved"), tr("Document not saved, sure you want to quit?")) != QMessageBox::Yes) { - return; - } - } - close(); -} +MainWindow::~MainWindow() { delete ui; } diff --git a/client/qmarkdowntextedit/mainwindow.h b/client/qmarkdowntextedit/mainwindow.h index f3487ac..13c2de9 100644 --- a/client/qmarkdowntextedit/mainwindow.h +++ b/client/qmarkdowntextedit/mainwindow.h @@ -1,15 +1,25 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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. */ #pragma once @@ -20,25 +30,13 @@ namespace Ui { class MainWindow; } -class MainWindow : public QMainWindow -{ +class MainWindow : public QMainWindow { Q_OBJECT -public: + public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void loadFile(const QString &filename); - void saveToFile(const QString &filename); - -private slots: - void open(); - void save(); - void saveAs(); - void onQuit(); - -private: + private: Ui::MainWindow *ui; - QString m_loadedContent; - QString m_filename; }; diff --git a/client/qmarkdowntextedit/mainwindow.ui b/client/qmarkdowntextedit/mainwindow.ui index a5b9a5b..3ee341f 100644 --- a/client/qmarkdowntextedit/mainwindow.ui +++ b/client/qmarkdowntextedit/mainwindow.ui @@ -26,7 +26,9 @@ ## Features - markdown highlighting +- syntax highlighting - clickable links with `Ctrl + Click` +- ~strikedout~ text and `inline code;` - block indent with `Tab` and `Shift + Tab` - duplicate text with `Ctrl + Alt + Down` - searching of text with `Ctrl + F` @@ -36,7 +38,7 @@ ## References -- [QOwnNotes - cross-platform open source plain-text notepad](http://www.qownnotes.org) +- [QOwnNotes - cross-platform open source plain-text file markdown note taking](https://www.qownnotes.org) ## Disclaimer @@ -55,7 +57,7 @@ There are inherent dangers in the use of any software, and you are solely respon 0 0 1070 - 25 + 23 diff --git a/client/qmarkdowntextedit/markdownhighlighter.cpp b/client/qmarkdowntextedit/markdownhighlighter.cpp index f99daed..4c9dee4 100644 --- a/client/qmarkdowntextedit/markdownhighlighter.cpp +++ b/client/qmarkdowntextedit/markdownhighlighter.cpp @@ -1,42 +1,71 @@ + /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- + * Copyright (c) 2019-2021 Waqar Ahmed -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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: * - * QPlainTextEdit markdown highlighter + * The above copyright notice and this permission notice 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. + * + * QPlainTextEdit Markdown highlighter */ -#include -#include #include "markdownhighlighter.h" + +#include #include #include #include +#include +#include +#include +#include "qownlanguagedata.h" + +// We enable QStringView with Qt 5.15.14 +// Note: QStringView::mid wasn't working correctly at least with 5.15.2 +// and 5.15.3, but 5.15.14 was fine +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 14) +#define MH_SUBSTR(pos, len) text.midRef(pos, len) +#else +#define MH_SUBSTR(pos, len) QStringView(text).mid(pos, len) +#endif + +QHash + MarkdownHighlighter::_langStringToEnum; +QHash + MarkdownHighlighter::_formats; +QVector + MarkdownHighlighter::_highlightingRules; /** * Markdown syntax highlighting - * - * markdown syntax: - * http://daringfireball.net/projects/markdown/syntax - * * @param parent * @return */ MarkdownHighlighter::MarkdownHighlighter( - QTextDocument *parent, HighlightingOptions highlightingOptions) - : QSyntaxHighlighter(parent) { - _highlightingOptions = highlightingOptions; + QTextDocument *parent, HighlightingOptions highlightingOptions) + : QSyntaxHighlighter(parent), _highlightingOptions(highlightingOptions) { + // _highlightingOptions = highlightingOptions; _timer = new QTimer(this); - QObject::connect(_timer, SIGNAL(timeout()), - this, SLOT(timerTick())); + connect(_timer, &QTimer::timeout, this, &MarkdownHighlighter::timerTick); + _timer->start(1000); // initialize the highlighting rules @@ -44,21 +73,22 @@ MarkdownHighlighter::MarkdownHighlighter( // initialize the text formats initTextFormats(); + + // initialize code languages + initCodeLangs(); } /** * Does jobs every second */ void MarkdownHighlighter::timerTick() { - // qDebug() << "timerTick: " << this << ", " << this->parent()->parent()->parent()->objectName(); - // re-highlight all dirty blocks reHighlightDirtyBlocks(); // emit a signal every second if there was some highlighting done if (_highlightingFinished) { _highlightingFinished = false; - emit(highlightingFinished()); + Q_EMIT highlightingFinished(); } } @@ -77,6 +107,7 @@ void MarkdownHighlighter::reHighlightDirtyBlocks() { * Clears the dirty blocks vector */ void MarkdownHighlighter::clearDirtyBlocks() { + _ranges.clear(); _dirtyTextBlocks.clear(); } @@ -85,7 +116,7 @@ void MarkdownHighlighter::clearDirtyBlocks() { * * @param block */ -void MarkdownHighlighter::addDirtyBlock(QTextBlock block) { +void MarkdownHighlighter::addDirtyBlock(const QTextBlock &block) { if (!_dirtyTextBlocks.contains(block)) { _dirtyTextBlocks.append(block); } @@ -101,178 +132,53 @@ void MarkdownHighlighter::addDirtyBlock(QTextBlock block) { * /usr/share/kde4/apps/katepart/syntax/markdown.xml */ void MarkdownHighlighter::initHighlightingRules() { - // highlight the reference of reference links - { - HighlightingRule rule(HighlighterState::MaskedSyntax); - rule.pattern = QRegularExpression("^\\[.+?\\]: \\w+://.+$"); - _highlightingRulesPre.append(rule); - } - - // highlight unordered lists - { - HighlightingRule rule(HighlighterState::List); - rule.pattern = QRegularExpression("^\\s*[-*+]\\s"); - rule.useStateAsCurrentBlockState = true; - _highlightingRulesPre.append(rule); - - // highlight ordered lists - rule.pattern = QRegularExpression("^\\s*\\d+\\.\\s"); - _highlightingRulesPre.append(rule); - } - // highlight block quotes { HighlightingRule rule(HighlighterState::BlockQuote); rule.pattern = QRegularExpression( - _highlightingOptions.testFlag( - HighlightingOption::FullyHighlightedBlockQuote) ? - "^\\s*(>\\s*.+)" : "^\\s*(>\\s*)+"); - _highlightingRulesPre.append(rule); - } - - // highlight horizontal rulers - { - HighlightingRule rule(HighlighterState::HorizontalRuler); - rule.pattern = QRegularExpression("^([*\\-_]\\s?){3,}$"); - _highlightingRulesPre.append(rule); + _highlightingOptions.testFlag( + HighlightingOption::FullyHighlightedBlockQuote) + ? QStringLiteral("^\\s*(>\\s*.+)") + : QStringLiteral("^\\s*(>\\s*)+")); + rule.shouldContain = QStringLiteral("> "); + _highlightingRules.append(rule); } // highlight tables without starting | // we drop that for now, it's far too messy to deal with -// rule = HighlightingRule(); -// rule.pattern = QRegularExpression("^.+? \\| .+? \\| .+$"); -// rule.state = HighlighterState::Table; -// _highlightingRulesPre.append(rule); - - /* - * highlight italic - * this goes before bold so that bold can overwrite italic - * - * text to test: - * **bold** normal **bold** - * *start of line* normal - * normal *end of line* - * * list item *italic* - */ + // rule = HighlightingRule(); + // rule.pattern = QRegularExpression("^.+? \\| .+? \\| .+$"); + // rule.state = HighlighterState::Table; + // _highlightingRulesPre.append(rule); + // highlight trailing spaces { - HighlightingRule rule(HighlighterState::Italic); - // we don't allow a space after the starting * to prevent problems with - // unordered lists starting with a * - rule.pattern = QRegularExpression( - "(?:^|[^\\*\\b])(?:\\*([^\\* ][^\\*]*?)\\*)(?:[^\\*\\b]|$)"); + HighlightingRule rule(HighlighterState::TrailingSpace); + rule.pattern = QRegularExpression(QStringLiteral("( +)$")); + rule.shouldContain = QStringLiteral(" "); rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - - rule.pattern = QRegularExpression("\\b_([^_]+)_\\b"); - _highlightingRulesAfter.append(rule); - } - - { - HighlightingRule rule(HighlighterState::Bold); - // highlight bold - rule.pattern = QRegularExpression("\\B\\*{2}(.+?)\\*{2}\\B"); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - rule.pattern = QRegularExpression("\\b__(.+?)__\\b"); - _highlightingRulesAfter.append(rule); - } - - // highlight urls - { - HighlightingRule rule(HighlighterState::Link); - - // highlight urls without any other markup - rule.pattern = QRegularExpression("\\b\\w+?:\\/\\/[^\\s]+"); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - - // rule.pattern = QRegularExpression("<(.+?:\\/\\/.+?)>"); - rule.pattern = QRegularExpression("<([^\\s`][^`]*?[^\\s`])>"); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - - // highlight urls with title - // rule.pattern = QRegularExpression("\\[(.+?)\\]\\(.+?://.+?\\)"); - // rule.pattern = QRegularExpression("\\[(.+?)\\]\\(.+\\)\\B"); - rule.pattern = QRegularExpression("\\[([^\\[\\]]+)\\]\\((\\S+|.+?)\\)\\B"); - _highlightingRulesAfter.append(rule); - - // highlight urls with empty title - // rule.pattern = QRegularExpression("\\[\\]\\((.+?://.+?)\\)"); - rule.pattern = QRegularExpression("\\[\\]\\((.+?)\\)"); - _highlightingRulesAfter.append(rule); - - // highlight email links - rule.pattern = QRegularExpression("<(.+?@.+?)>"); - _highlightingRulesAfter.append(rule); - - // highlight reference links - rule.pattern = QRegularExpression("\\[(.+?)\\]\\s?\\[.+?\\]"); - _highlightingRulesAfter.append(rule); - } - - // Images - { - // highlight images with text - HighlightingRule rule(HighlighterState::Image); - rule.pattern = QRegularExpression("!\\[(.+?)\\]\\(.+?\\)"); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - - // highlight images without text - rule.pattern = QRegularExpression("!\\[\\]\\((.+?)\\)"); - _highlightingRulesAfter.append(rule); - } - - // highlight images links - { -// HighlightingRule rule; - HighlightingRule rule(HighlighterState::Link); - rule.pattern = QRegularExpression("\\[!\\[(.+?)\\]\\(.+?\\)\\]\\(.+?\\)"); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - - // highlight images links without text - rule.pattern = QRegularExpression("\\[!\\[\\]\\(.+?\\)\\]\\((.+?)\\)"); - _highlightingRulesAfter.append(rule); - } - - // highlight inline code - { - HighlightingRule rule(HighlighterState::InlineCodeBlock); -// HighlightingRule rule; - rule.pattern = QRegularExpression("`(.+?)`"); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - } - - // highlight code blocks with four spaces or tabs in front of them - // and no list character after that - { - HighlightingRule rule(HighlighterState::CodeBlock); -// HighlightingRule rule; - rule.pattern = QRegularExpression("^((\\t)|( {4,})).+$"); - rule.disableIfCurrentStateIsSet = true; - _highlightingRulesAfter.append(rule); + _highlightingRules.append(rule); } // highlight inline comments { + // highlight comments for R Markdown for academic papers HighlightingRule rule(HighlighterState::Comment); - rule.pattern = QRegularExpression(""); - rule.capturingGroup = 1; - _highlightingRulesAfter.append(rule); - - // highlight comments for Rmarkdown for academic papers - rule.pattern = QRegularExpression("^\\[.+?\\]: # \\(.+?\\)$"); - _highlightingRulesAfter.append(rule); + rule.pattern = + QRegularExpression(QStringLiteral(R"(^\[.+?\]: # \(.+?\)$)")); + rule.shouldContain = QStringLiteral("]: # ("); + _highlightingRules.append(rule); } // highlight tables with starting | { HighlightingRule rule(HighlighterState::Table); - rule.pattern = QRegularExpression("^\\|.+?\\|$"); - _highlightingRulesAfter.append(rule); + rule.shouldContain = QStringLiteral("|"); + // Support up to 3 leading spaces, because md4c seems to support it + // See https://github.com/pbek/QOwnNotes/issues/3137 + rule.pattern = + QRegularExpression(QStringLiteral("^\\s{0,3}(\\|.+?\\|)$")); + rule.capturingGroup = 1; + _highlightingRules.append(rule); } } @@ -286,7 +192,7 @@ void MarkdownHighlighter::initTextFormats(int defaultFontSize) { // set character formats for headlines format = QTextCharFormat(); - //format.setForeground(QBrush(QColor(0, 49, 110))); + format.setForeground(QColor(2, 69, 150)); format.setFontWeight(QFont::Bold); format.setFontPointSize(defaultFontSize * 1.6); _formats[H1] = format; @@ -304,31 +210,40 @@ void MarkdownHighlighter::initTextFormats(int defaultFontSize) { // set character format for horizontal rulers format = QTextCharFormat(); - //format.setForeground(QBrush(Qt::darkGray)); - //format.setBackground(QBrush(Qt::lightGray)); - _formats[HorizontalRuler] = format; + format.setForeground(Qt::darkGray); + format.setBackground(Qt::lightGray); + _formats[HorizontalRuler] = std::move(format); // set character format for lists format = QTextCharFormat(); - //format.setForeground(QBrush(QColor(163, 0, 123))); + format.setForeground(QColor(163, 0, 123)); _formats[List] = format; + // set character format for checkbox + format = QTextCharFormat(); + format.setForeground(QColor(123, 100, 223)); + _formats[CheckBoxUnChecked] = std::move(format); + // set character format for checked checkbox + format = QTextCharFormat(); + format.setForeground(QColor(223, 50, 123)); + _formats[CheckBoxChecked] = std::move(format); + // set character format for links format = QTextCharFormat(); - //format.setForeground(QBrush(QColor(0, 128, 255))); + format.setForeground(QColor(0, 128, 255)); format.setFontUnderline(true); - _formats[Link] = format; + _formats[Link] = std::move(format); // set character format for images format = QTextCharFormat(); - //format.setForeground(QBrush(QColor(0, 191, 0))); - //format.setBackground(QBrush(QColor(228, 255, 228))); - _formats[Image] = format; + format.setForeground(QColor(0, 191, 0)); + format.setBackground(QColor(228, 255, 228)); + _formats[Image] = std::move(format); // set character format for code blocks format = QTextCharFormat(); format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - //format.setBackground(QColor(220, 220, 220)); + // format.setBackground(QColor(220, 220, 220)); _formats[CodeBlock] = format; _formats[InlineCodeBlock] = format; @@ -336,39 +251,133 @@ void MarkdownHighlighter::initTextFormats(int defaultFontSize) { format = QTextCharFormat(); format.setFontWeight(QFont::StyleItalic); format.setFontItalic(true); - _formats[Italic] = format; + _formats[Italic] = std::move(format); + + // set character format for underline + format = QTextCharFormat(); + format.setFontUnderline(true); + _formats[StUnderline] = std::move(format); // set character format for bold format = QTextCharFormat(); format.setFontWeight(QFont::Bold); - _formats[Bold] = format; + _formats[Bold] = std::move(format); // set character format for comments format = QTextCharFormat(); - format.setForeground(QBrush(Qt::lightGray)); - _formats[Comment] = format; + format.setForeground(QBrush(Qt::gray)); + _formats[Comment] = std::move(format); // set character format for masked syntax format = QTextCharFormat(); - //format.setForeground(QBrush("#cccccc")); - _formats[MaskedSyntax] = format; + format.setForeground(QColor(204, 204, 204)); + _formats[MaskedSyntax] = std::move(format); // set character format for tables format = QTextCharFormat(); format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - //format.setForeground(QBrush(QColor("#649449"))); - _formats[Table] = format; + format.setForeground(QColor(100, 148, 73)); + _formats[Table] = std::move(format); // set character format for block quotes format = QTextCharFormat(); - //format.setForeground(QBrush(QColor(Qt::darkRed))); - _formats[BlockQuote] = format; + format.setForeground(Qt::darkRed); + _formats[BlockQuote] = std::move(format); format = QTextCharFormat(); - _formats[HeadlineEnd] = format; + _formats[HeadlineEnd] = std::move(format); + _formats[NoState] = std::move(format); + + // set character format for trailing spaces + format.setBackground(QColor(252, 175, 62)); + _formats[TrailingSpace] = std::move(format); + + /**************************************** + * Formats for syntax highlighting + ***************************************/ format = QTextCharFormat(); - _formats[NoState] = format; + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(249, 38, 114)); + _formats[CodeKeyWord] = std::move(format); + + format = QTextCharFormat(); + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(163, 155, 78)); + _formats[CodeString] = std::move(format); + + format = QTextCharFormat(); + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(117, 113, 94)); + _formats[CodeComment] = std::move(format); + + format = QTextCharFormat(); + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(84, 174, 191)); + _formats[CodeType] = std::move(format); + + format = QTextCharFormat(); + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(219, 135, 68)); + _formats[CodeOther] = std::move(format); + + format = QTextCharFormat(); + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(174, 129, 255)); + _formats[CodeNumLiteral] = std::move(format); + + format = QTextCharFormat(); + format.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + format.setForeground(QColor(1, 138, 15)); + _formats[CodeBuiltIn] = std::move(format); +} + +/** + * @brief initializes the langStringToEnum + */ +void MarkdownHighlighter::initCodeLangs() { + MarkdownHighlighter::_langStringToEnum = + QHash{ + {QLatin1String("bash"), MarkdownHighlighter::CodeBash}, + {QLatin1String("c"), MarkdownHighlighter::CodeC}, + {QLatin1String("cpp"), MarkdownHighlighter::CodeCpp}, + {QLatin1String("cxx"), MarkdownHighlighter::CodeCpp}, + {QLatin1String("c++"), MarkdownHighlighter::CodeCpp}, + {QLatin1String("c#"), MarkdownHighlighter::CodeCSharp}, + {QLatin1String("cmake"), MarkdownHighlighter::CodeCMake}, + {QLatin1String("csharp"), MarkdownHighlighter::CodeCSharp}, + {QLatin1String("css"), MarkdownHighlighter::CodeCSS}, + {QLatin1String("go"), MarkdownHighlighter::CodeGo}, + {QLatin1String("html"), MarkdownHighlighter::CodeXML}, + {QLatin1String("ini"), MarkdownHighlighter::CodeINI}, + {QLatin1String("java"), MarkdownHighlighter::CodeJava}, + {QLatin1String("javascript"), MarkdownHighlighter::CodeJava}, + {QLatin1String("js"), MarkdownHighlighter::CodeJs}, + {QLatin1String("json"), MarkdownHighlighter::CodeJSON}, + {QLatin1String("make"), MarkdownHighlighter::CodeMake}, + {QLatin1String("nix"), MarkdownHighlighter::CodeNix}, + {QLatin1String("php"), MarkdownHighlighter::CodePHP}, + {QLatin1String("py"), MarkdownHighlighter::CodePython}, + {QLatin1String("python"), MarkdownHighlighter::CodePython}, + {QLatin1String("qml"), MarkdownHighlighter::CodeQML}, + {QLatin1String("rust"), MarkdownHighlighter::CodeRust}, + {QLatin1String("sh"), MarkdownHighlighter::CodeBash}, + {QLatin1String("sql"), MarkdownHighlighter::CodeSQL}, + {QLatin1String("taggerscript"), + MarkdownHighlighter::CodeTaggerScript}, + {QLatin1String("ts"), MarkdownHighlighter::CodeTypeScript}, + {QLatin1String("typescript"), MarkdownHighlighter::CodeTypeScript}, + {QLatin1String("v"), MarkdownHighlighter::CodeV}, + {QLatin1String("vex"), MarkdownHighlighter::CodeVex}, + {QLatin1String("xml"), MarkdownHighlighter::CodeXML}, + {QLatin1String("yml"), MarkdownHighlighter::CodeYAML}, + {QLatin1String("yaml"), MarkdownHighlighter::CodeYAML}, + {QLatin1String("forth"), MarkdownHighlighter::CodeForth}, + {QLatin1String("systemverilog"), + MarkdownHighlighter::CodeSystemVerilog}, + {QLatin1String("gdscript"), MarkdownHighlighter::CodeGDScript}, + {QLatin1String("toml"), MarkdownHighlighter::CodeTOML}, + }; } /** @@ -377,8 +386,8 @@ void MarkdownHighlighter::initTextFormats(int defaultFontSize) { * @param formats */ void MarkdownHighlighter::setTextFormats( - QHash formats) { - _formats = formats; + QHash formats) { + _formats = std::move(formats); } /** @@ -388,33 +397,130 @@ void MarkdownHighlighter::setTextFormats( */ void MarkdownHighlighter::setTextFormat(HighlighterState state, QTextCharFormat format) { - _formats[state] = format; + _formats[state] = std::move(format); } /** - * Does the markdown highlighting + * Does the Markdown highlighting * * @param text */ void MarkdownHighlighter::highlightBlock(const QString &text) { + if (currentBlockState() == HeadlineEnd) { + currentBlock().previous().setUserState(NoState); + addDirtyBlock(currentBlock().previous()); + } setCurrentBlockState(HighlighterState::NoState); currentBlock().setUserState(HighlighterState::NoState); + highlightMarkdown(text); _highlightingFinished = true; } -void MarkdownHighlighter::highlightMarkdown(QString text) { - if (!text.isEmpty()) { - highlightAdditionalRules(_highlightingRulesPre, text); +void MarkdownHighlighter::highlightMarkdown(const QString &text) { + const bool isBlockCodeBlock = isCodeBlock(previousBlockState()) || + text.startsWith(QLatin1String("```")) || + text.startsWith(QLatin1String("~~~")); + + if (!text.isEmpty() && !isBlockCodeBlock) { + highlightAdditionalRules(_highlightingRules, text); + + highlightThematicBreak(text); // needs to be called after the horizontal ruler highlighting highlightHeadline(text); - highlightAdditionalRules(_highlightingRulesAfter, text); + highlightIndentedCodeBlock(text); + + highlightLists(text); + + highlightInlineRules(text); } highlightCommentBlock(text); - highlightCodeBlock(text); + if (isBlockCodeBlock) highlightCodeFence(text); + highlightFrontmatterBlock(text); +} + +/** + * @brief gets indentation(spaces) of text + * @param text + * @return 1, if 1 space, 2 if 2 spaces, 3 if 3 spaces. Otherwise 0 + */ +static int getIndentation(const QString &text) { + int spaces = 0; + // no more than 3 spaces + while (spaces < 4 && spaces < text.length() && + text.at(spaces) == QLatin1Char(' ')) + ++spaces; + return spaces; +} + +static bool isParagraph(const QString &text) { + // blank line + if (text.isEmpty()) return false; + int indent = getIndentation(text); + // code block + if (indent >= 4) return false; + + const auto textView = MH_SUBSTR(indent, -1); + if (textView.isEmpty()) return false; + + // unordered listtextView + if (textView.startsWith(QStringLiteral("- ")) || + textView.startsWith(QStringLiteral("+ ")) || + textView.startsWith(QStringLiteral("* "))) { + return false; + } + // block quote + if (textView.startsWith(QStringLiteral("> "))) return false; + // atx heading + if (textView.startsWith(QStringLiteral("#"))) { + int firstSpace = textView.indexOf(' '); + if (firstSpace > 0 && firstSpace <= 7) { + return false; + } + } + // hr + auto isThematicBreak = [textView]() { + return std::all_of(textView.begin(), textView.end(), + [](QChar c) { + auto ch = c.unicode(); + return ch == '-' || ch == ' ' || ch == '\t'; + }) || + std::all_of(textView.begin(), textView.end(), + [](QChar c) { + auto ch = c.unicode(); + return ch == '+' || ch == ' ' || ch == '\t'; + }) || + std::all_of(textView.begin(), textView.end(), [](QChar c) { + auto ch = c.unicode(); + return ch == '*' || ch == ' ' || ch == '\t'; + }); + }; + if (isThematicBreak()) return false; + // ordered list + if (textView.at(0).isDigit()) { + int i = 1; + int count = 1; + for (; i < textView.size(); ++i) { + if (textView[i].isDigit()) { + count++; + continue; + } else + break; + } + + // ordered list marker can't be more than 9 numbers + if (count <= 9 && i + 1 < textView.size() && + (textView[i] == QLatin1Char('.') || + textView[i] == QLatin1Char(')')) && + textView[i + 1] == QLatin1Char(' ')) { + return false; + } + } + + return true; } /** @@ -422,163 +528,179 @@ void MarkdownHighlighter::highlightMarkdown(QString text) { * * @param text */ -void MarkdownHighlighter::highlightHeadline(QString text) { - QRegularExpression regex("^(#+)\\s+(.+?)$"); - QRegularExpressionMatch match = regex.match(text); - QTextCharFormat &maskedFormat = _formats[HighlighterState::MaskedSyntax]; +void MarkdownHighlighter::highlightHeadline(const QString &text) { + // three spaces indentation is allowed in headings + const int spacesOffset = getIndentation(text); - // check for headline blocks with # in front of them - if (match.hasMatch()) { - int count = match.captured(1).count(); + if (spacesOffset >= text.length() || spacesOffset == 4) return; - // we just have H1 to H6 - count = qMin(count, 6); + const bool headingFound = text.at(spacesOffset) == QLatin1Char('#'); - HighlighterState state = HighlighterState( - HighlighterState::H1 + count - 1); + if (headingFound) { + int headingLevel = 0; + int i = spacesOffset; + if (i >= text.length()) return; + while (i < text.length() && text.at(i) == QLatin1Char('#') && + i < (spacesOffset + 6)) + ++i; - QTextCharFormat &format = _formats[state]; - QTextCharFormat currentMaskedFormat = maskedFormat; + if (i < text.length() && text.at(i) == QLatin1Char(' ')) + headingLevel = i - spacesOffset; - // set the font size from the current rule's font format - currentMaskedFormat.setFontPointSize(format.fontPointSize()); + if (headingLevel > 0) { + const auto state = + HighlighterState(HighlighterState::H1 + headingLevel - 1); - // first highlight everything as MaskedSyntax - setFormat(match.capturedStart(), match.capturedLength(), - currentMaskedFormat); + // Set styling of the "#"s to "masked syntax", but with the size of + // the heading + auto maskedFormat = _formats[MaskedSyntax]; + maskedFormat.setFontPointSize(_formats[state].fontPointSize()); + setFormat(0, headingLevel, maskedFormat); - // then highlight with the real format - setFormat(match.capturedStart(2), match.capturedLength(2), - _formats[state]); + // Set the styling of the rest of the heading + setFormat(headingLevel + 1, text.length() - 1 - headingLevel, + _formats[state]); - // set a margin for the current block - setCurrentBlockMargin(state); - - setCurrentBlockState(state); - currentBlock().setUserState(state); - return; + setCurrentBlockState(state); + return; + } } + auto hasOnlyHeadChars = [](const QString &txt, const QChar c, + int spaces) -> bool { + if (txt.isEmpty()) return false; + for (int i = spaces; i < txt.length(); ++i) { + if (txt.at(i) != c) return false; + } + return true; + }; + // take care of ==== and ---- headlines - QRegularExpression patternH1 = QRegularExpression("^=+$"); - QRegularExpression patternH2 = QRegularExpression("^-+$"); + const QString prev = currentBlock().previous().text(); + auto prevSpaces = getIndentation(prev); + const bool isPrevParagraph = isParagraph(prev); + + if (text.at(spacesOffset) == QLatin1Char('=') && prevSpaces < 4 && + isPrevParagraph) { + const bool pattern1 = + !prev.isEmpty() && + hasOnlyHeadChars(text, QLatin1Char('='), spacesOffset); + if (pattern1) { + highlightSubHeadline(text, H1); + return; + } + } else if (text.at(spacesOffset) == QLatin1Char('-') && prevSpaces < 4 && + isPrevParagraph) { + const bool pattern2 = + !prev.isEmpty() && + hasOnlyHeadChars(text, QLatin1Char('-'), spacesOffset); + if (pattern2) { + highlightSubHeadline(text, H2); + return; + } + } + + const QString nextBlockText = currentBlock().next().text(); + if (nextBlockText.isEmpty()) return; + const int nextSpaces = getIndentation(nextBlockText); + const bool isCurrentParagraph = isParagraph(text); + + if (nextSpaces >= nextBlockText.length()) return; + + if (nextBlockText.at(nextSpaces) == QLatin1Char('=') && nextSpaces < 4 && + isCurrentParagraph) { + const bool nextHasEqualChars = + hasOnlyHeadChars(nextBlockText, QLatin1Char('='), nextSpaces); + if (nextHasEqualChars) { + setFormat(0, text.length(), _formats[HighlighterState::H1]); + setCurrentBlockState(HighlighterState::H1); + } + } else if (nextBlockText.at(nextSpaces) == QLatin1Char('-') && + nextSpaces < 4 && isCurrentParagraph) { + const bool nextHasMinusChars = + hasOnlyHeadChars(nextBlockText, QLatin1Char('-'), nextSpaces); + if (nextHasMinusChars) { + setFormat(0, text.length(), _formats[HighlighterState::H2]); + setCurrentBlockState(HighlighterState::H2); + } + } +} + +void MarkdownHighlighter::highlightSubHeadline(const QString &text, + HighlighterState state) { + const QTextCharFormat &maskedFormat = + _formats[HighlighterState::MaskedSyntax]; QTextBlock previousBlock = currentBlock().previous(); - QString previousText = previousBlock.text(); - previousText.trimmed().remove(QRegularExpression("[=-]")); - // check for ===== after a headline text and highlight as H1 - if (patternH1.match(text).hasMatch()) { - if (((previousBlockState() == HighlighterState::H1) || - (previousBlockState() == HighlighterState::NoState)) && - (previousText.length() > 0)) { - // set the font size from the current rule's font format - QTextCharFormat currentMaskedFormat = maskedFormat; - currentMaskedFormat.setFontPointSize( - _formats[HighlighterState::H1].fontPointSize()); + // we check for both H1/H2 so that if the user changes his mind, and changes + // === to ---, changes be reflected immediately + if (previousBlockState() == H1 || previousBlockState() == H2 || + previousBlockState() == NoState) { + QTextCharFormat currentMaskedFormat = maskedFormat; + // set the font size from the current rule's font format + currentMaskedFormat.setFontPointSize(_formats[state].fontPointSize()); - setFormat(0, text.length(), currentMaskedFormat); - setCurrentBlockState(HighlighterState::HeadlineEnd); - previousBlock.setUserState(HighlighterState::H1); + setFormat(0, text.length(), currentMaskedFormat); + setCurrentBlockState(HeadlineEnd); - // set a margin for the current block - setCurrentBlockMargin(HighlighterState::H1); - - // we want to re-highlight the previous block - // this must not done directly, but with a queue, otherwise it - // will crash - // setting the character format of the previous text, because this - // causes text to be formatted the same way when writing after - // the text + // we want to re-highlight the previous block + // this must not be done directly, but with a queue, otherwise it + // will crash + // setting the character format of the previous text, because this + // causes text to be formatted the same way when writing after + // the text + if (previousBlockState() != state) { addDirtyBlock(previousBlock); + previousBlock.setUserState(state); } - - return; - } - - // check for ----- after a headline text and highlight as H2 - if (patternH2.match(text).hasMatch()) { - if (((previousBlockState() == HighlighterState::H2) || - (previousBlockState() == HighlighterState::NoState)) && - (previousText.length() > 0)) { - // set the font size from the current rule's font format - QTextCharFormat currentMaskedFormat = maskedFormat; - currentMaskedFormat.setFontPointSize( - _formats[HighlighterState::H2].fontPointSize()); - - setFormat(0, text.length(), currentMaskedFormat); - setCurrentBlockState(HighlighterState::HeadlineEnd); - previousBlock.setUserState(HighlighterState::H2); - - // set a margin for the current block - setCurrentBlockMargin(HighlighterState::H2); - - // we want to re-highlight the previous block - addDirtyBlock(previousBlock); - } - - return; - } - - QTextBlock nextBlock = currentBlock().next(); - QString nextBlockText = nextBlock.text(); - - // highlight as H1 if next block is ===== - if (patternH1.match(nextBlockText).hasMatch() || - patternH2.match(nextBlockText).hasMatch()) { - setFormat(0, text.length(), _formats[HighlighterState::H1]); - setCurrentBlockState(HighlighterState::H1); - currentBlock().setUserState(HighlighterState::H1); - } - - // highlight as H2 if next block is ----- - if (patternH2.match(nextBlockText).hasMatch()) { - setFormat(0, text.length(), _formats[HighlighterState::H2]); - setCurrentBlockState(HighlighterState::H2); - currentBlock().setUserState(HighlighterState::H2); } } /** - * Sets a margin for the current block - * - * @param state + * @brief highlight code blocks with four spaces or tabs in front of them + * and no list character after that + * @param text */ -void MarkdownHighlighter::setCurrentBlockMargin( - MarkdownHighlighter::HighlighterState state) { - // this is currently disabled because it causes multiple problems: - // - it prevents "undo" in headlines - // https://github.com/pbek/QOwnNotes/issues/520 - // - invisible lines at the end of a note - // https://github.com/pbek/QOwnNotes/issues/667 - // - a crash when reaching the invisible lines when the current line is - // highlighted - // https://github.com/pbek/QOwnNotes/issues/701 - return; +void MarkdownHighlighter::highlightIndentedCodeBlock(const QString &text) { + if (text.isEmpty() || (!text.startsWith(QLatin1String(" ")) && + !text.startsWith(QLatin1Char('\t')))) + return; - qreal margin; + const QString prevTrimmed = currentBlock().previous().text().trimmed(); + // previous line must be empty according to CommonMark except if it is a + // heading https://spec.commonmark.org/0.29/#indented-code-block + if (!prevTrimmed.isEmpty() && previousBlockState() != CodeBlockIndented && + !isHeading(previousBlockState()) && previousBlockState() != HeadlineEnd) + return; - switch (state) { - case HighlighterState::H1: - margin = 5; - break; - case HighlighterState::H2: - case HighlighterState::H3: - case HighlighterState::H4: - case HighlighterState::H5: - case HighlighterState::H6: - margin = 3; - break; - default: - return; + const QString trimmed = text.trimmed(); + + // should not be in a list + if (trimmed.startsWith(QLatin1String("- ")) || + trimmed.startsWith(QLatin1String("+ ")) || + trimmed.startsWith(QLatin1String("* ")) || + (trimmed.length() >= 1 && trimmed.at(0).isNumber())) + return; + + setCurrentBlockState(CodeBlockIndented); + setFormat(0, text.length(), _formats[CodeBlock]); +} + +void MarkdownHighlighter::highlightCodeFence(const QString &text) { + // already in tilde block + if ((previousBlockState() == CodeBlockTilde || + previousBlockState() == CodeBlockTildeComment || + previousBlockState() >= CodeCpp + tildeOffset)) { + highlightCodeBlock(text, QStringLiteral("~~~")); + // start of a tilde block + } else if ((previousBlockState() != CodeBlock && + previousBlockState() < CodeCpp) && + text.startsWith(QLatin1String("~~~"))) { + highlightCodeBlock(text, QStringLiteral("~~~")); + } else { + // back tick block + highlightCodeBlock(text); } - - QTextBlockFormat blockFormat = currentBlock().blockFormat(); - blockFormat.setTopMargin(2); - blockFormat.setBottomMargin(margin); - - // this prevents "undo" in headlines! - QTextCursor* myCursor = new QTextCursor(currentBlock()); - myCursor->setBlockFormat(blockFormat); } /** @@ -586,24 +708,1254 @@ void MarkdownHighlighter::setCurrentBlockMargin( * * @param text */ -void MarkdownHighlighter::highlightCodeBlock(QString text) { - QRegularExpression regex("^```\\w*?$"); - QRegularExpressionMatch match = regex.match(text); +void MarkdownHighlighter::highlightCodeBlock(const QString &text, + const QString &opener) { + if (text.startsWith(opener)) { + // if someone decides to put these on the same line + // interpret it as inline code, not code block + if (text.endsWith(QLatin1String("```")) && text.length() > 3) { + setFormat(3, text.length() - 3, + _formats[HighlighterState::InlineCodeBlock]); + setFormat(0, 3, _formats[HighlighterState::MaskedSyntax]); + setFormat(text.length() - 3, 3, + _formats[HighlighterState::MaskedSyntax]); + return; + } + if ((previousBlockState() != CodeBlock && + previousBlockState() != CodeBlockTilde) && + (previousBlockState() != CodeBlockComment && + previousBlockState() != CodeBlockTildeComment) && + previousBlockState() < CodeCpp) { + const QString &lang = text.mid(3, text.length()).toLower(); + HighlighterState progLang = _langStringToEnum.value(lang); + + if (progLang >= CodeCpp) { + const int state = text.startsWith(QLatin1String("```")) + ? progLang + : progLang + tildeOffset; + setCurrentBlockState(state); + } else { + const int state = + opener == QLatin1String("```") ? CodeBlock : CodeBlockTilde; + setCurrentBlockState(state); + } + } else if (isCodeBlock(previousBlockState())) { + const int state = opener == QLatin1String("```") + ? CodeBlockEnd + : CodeBlockTildeEnd; + setCurrentBlockState(state); + } - if (match.hasMatch()) { - setCurrentBlockState( - previousBlockState() == HighlighterState::CodeBlock ? - HighlighterState::CodeBlockEnd : HighlighterState::CodeBlock); // set the font size from the current rule's font format - QTextCharFormat &maskedFormat = - _formats[HighlighterState::MaskedSyntax]; - maskedFormat.setFontPointSize( - _formats[HighlighterState::CodeBlock].fontPointSize()); + QTextCharFormat &maskedFormat = _formats[MaskedSyntax]; + maskedFormat.setFontPointSize(_formats[CodeBlock].fontPointSize()); setFormat(0, text.length(), maskedFormat); - } else if (previousBlockState() == HighlighterState::CodeBlock) { - setCurrentBlockState(HighlighterState::CodeBlock); - setFormat(0, text.length(), _formats[HighlighterState::CodeBlock]); + } else if (isCodeBlock(previousBlockState())) { + setCurrentBlockState(previousBlockState()); + highlightSyntax(text); + } +} + +/** + * @brief Does the code syntax highlighting + * @param text + */ +void MarkdownHighlighter::highlightSyntax(const QString &text) { + if (text.isEmpty()) return; + + const auto textLen = text.length(); + + QChar comment; + bool isCSS = false; + bool isYAML = false; + bool isMake = false; + bool isForth = false; + bool isGDScript = false; + bool isSQL = false; + bool isTOML = false; + + QMultiHash keywords{}; + QMultiHash others{}; + QMultiHash types{}; + QMultiHash builtin{}; + QMultiHash literals{}; + + // apply the default code block format first + setFormat(0, textLen, _formats[CodeBlock]); + + switch (currentBlockState()) { + case HighlighterState::CodeCpp: + case HighlighterState::CodeCpp + tildeOffset: + case HighlighterState::CodeCppComment: + case HighlighterState::CodeCppComment + tildeOffset: + loadCppData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeJs: + case HighlighterState::CodeJs + tildeOffset: + case HighlighterState::CodeJsComment: + case HighlighterState::CodeJsComment + tildeOffset: + loadJSData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeC: + case HighlighterState::CodeC + tildeOffset: + case HighlighterState::CodeCComment: + case HighlighterState::CodeCComment + tildeOffset: + loadCppData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeBash: + case HighlighterState::CodeBash + tildeOffset: + loadShellData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + case HighlighterState::CodePHP: + case HighlighterState::CodePHP + tildeOffset: + case HighlighterState::CodePHPComment: + case HighlighterState::CodePHPComment + tildeOffset: + loadPHPData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeQML: + case HighlighterState::CodeQML + tildeOffset: + case HighlighterState::CodeQMLComment: + case HighlighterState::CodeQMLComment + tildeOffset: + loadQMLData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodePython: + case HighlighterState::CodePython + tildeOffset: + loadPythonData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + case HighlighterState::CodeRust: + case HighlighterState::CodeRust + tildeOffset: + case HighlighterState::CodeRustComment: + case HighlighterState::CodeRustComment + tildeOffset: + loadRustData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeJava: + case HighlighterState::CodeJava + tildeOffset: + case HighlighterState::CodeJavaComment: + case HighlighterState::CodeJavaComment + tildeOffset: + loadJavaData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeCSharp: + case HighlighterState::CodeCSharp + tildeOffset: + case HighlighterState::CodeCSharpComment: + case HighlighterState::CodeCSharpComment + tildeOffset: + loadCSharpData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeGo: + case HighlighterState::CodeGo + tildeOffset: + case HighlighterState::CodeGoComment: + case HighlighterState::CodeGoComment + tildeOffset: + loadGoData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeV: + case HighlighterState::CodeV + tildeOffset: + case HighlighterState::CodeVComment: + case HighlighterState::CodeVComment + tildeOffset: + loadVData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeSQL: + case HighlighterState::CodeSQL + tildeOffset: + case HighlighterState::CodeSQLComment: + case HighlighterState::CodeSQLComment + tildeOffset: + loadSQLData(types, keywords, builtin, literals, others); + isSQL = true; + comment = + QLatin1Char('-'); // prevent the default comment highlighting + break; + case HighlighterState::CodeJSON: + case HighlighterState::CodeJSON + tildeOffset: + loadJSONData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeXML: + case HighlighterState::CodeXML + tildeOffset: + xmlHighlighter(text); + return; + case HighlighterState::CodeCSS: + case HighlighterState::CodeCSS + tildeOffset: + case HighlighterState::CodeCSSComment: + case HighlighterState::CodeCSSComment + tildeOffset: + isCSS = true; + loadCSSData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeTypeScript: + case HighlighterState::CodeTypeScript + tildeOffset: + case HighlighterState::CodeTypeScriptComment: + case HighlighterState::CodeTypeScriptComment + tildeOffset: + loadTypescriptData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeYAML: + case HighlighterState::CodeYAML + tildeOffset: + isYAML = true; + comment = QLatin1Char('#'); + loadYAMLData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeINI: + case HighlighterState::CodeINI + tildeOffset: + iniHighlighter(text); + return; + case HighlighterState::CodeTaggerScript: + case HighlighterState::CodeTaggerScript + tildeOffset: + taggerScriptHighlighter(text); + return; + case HighlighterState::CodeVex: + case HighlighterState::CodeVex + tildeOffset: + case HighlighterState::CodeVexComment: + case HighlighterState::CodeVexComment + tildeOffset: + loadVEXData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeCMake: + case HighlighterState::CodeCMake + tildeOffset: + loadCMakeData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + case HighlighterState::CodeMake: + case HighlighterState::CodeMake + tildeOffset: + isMake = true; + loadMakeData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + case HighlighterState::CodeNix: + case HighlighterState::CodeNix + tildeOffset: + loadNixData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + case HighlighterState::CodeForth: + case HighlighterState::CodeForth + tildeOffset: + case HighlighterState::CodeForthComment: + case HighlighterState::CodeForthComment + tildeOffset: + isForth = true; + loadForthData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeSystemVerilog: + case HighlighterState::CodeSystemVerilogComment: + loadSystemVerilogData(types, keywords, builtin, literals, others); + break; + case HighlighterState::CodeGDScript: + case HighlighterState::CodeGDScript + tildeOffset: + isGDScript = true; + loadGDScriptData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + case HighlighterState::CodeTOML: + case HighlighterState::CodeTOML + tildeOffset: + case HighlighterState::CodeTOMLString: + case HighlighterState::CodeTOMLString + tildeOffset: + isTOML = true; + loadTOMLData(types, keywords, builtin, literals, others); + comment = QLatin1Char('#'); + break; + default: + setFormat(0, textLen, _formats[CodeBlock]); + return; + } + + auto applyCodeFormat = + [this](int i, const QMultiHash &data, + const QString &text, const QTextCharFormat &fmt) -> int { + // check if we are at the beginning OR if this is the start of a word + if (i == 0 || (!text.at(i - 1).isLetterOrNumber() && + text.at(i - 1) != QLatin1Char('_'))) { + const char c = text.at(i).toLatin1(); + auto it = data.find(c); + for (; it != data.end() && it.key() == c; ++it) { + // we have a word match check + // 1. if we are at the end + // 2. if we have a complete word + const QLatin1String &word = it.value(); + if (word == MH_SUBSTR(i, word.size()) && + (i + word.size() == text.length() || + (!text.at(i + word.size()).isLetterOrNumber() && + text.at(i + word.size()) != QLatin1Char('_')))) { + setFormat(i, word.size(), fmt); + i += word.size(); + } + } + } + return i; + }; + + const QTextCharFormat &formatType = _formats[CodeType]; + const QTextCharFormat &formatKeyword = _formats[CodeKeyWord]; + const QTextCharFormat &formatComment = _formats[CodeComment]; + const QTextCharFormat &formatNumLit = _formats[CodeNumLiteral]; + const QTextCharFormat &formatBuiltIn = _formats[CodeBuiltIn]; + const QTextCharFormat &formatOther = _formats[CodeOther]; + + for (int i = 0; i < textLen; ++i) { + if (currentBlockState() != -1 && currentBlockState() % 2 != 0) + goto Comment; + + while (i < textLen && !text[i].isLetter()) { + if (text[i].isSpace()) { + ++i; + // make sure we don't cross the bound + if (i == textLen) break; + if (text[i].isLetter()) break; + continue; + } + // inline comment + if (comment.isNull() && text[i] == QLatin1Char('/')) { + if ((i + 1) < textLen) { + if (text[i + 1] == QLatin1Char('/')) { + setFormat(i, textLen, formatComment); + return; + } else if (text[i + 1] == QLatin1Char('*')) { + Comment: + int next = text.indexOf(QLatin1String("*/"), i); + if (next == -1) { + // we didn't find a comment end. + // Check if we are already in a comment block + if (currentBlockState() % 2 == 0) + setCurrentBlockState(currentBlockState() + 1); + setFormat(i, textLen, formatComment); + return; + } else { + // we found a comment end + // mark this block as code if it was previously + // comment. First check if the comment ended on the + // same line. if modulo 2 is not equal to zero, it + // means we are in a comment, -1 will set this + // block's state as language + if (currentBlockState() % 2 != 0) { + setCurrentBlockState(currentBlockState() - 1); + } + next += 2; + setFormat(i, next - i, formatComment); + i = next; + if (i >= textLen) return; + } + } + } + } else if (text[i] == comment) { + setFormat(i, textLen, formatComment); + i = textLen; + break; + // integer literal + } else if (text[i].isNumber()) { + i = highlightNumericLiterals(text, i); + // string literals + } else if (text[i] == QLatin1Char('\"') || + text[i] == QLatin1Char('\'')) { + i = highlightStringLiterals(text.at(i), text, i); + } + if (i >= textLen) { + break; + } + ++i; + } + + const int pos = i; + + if (i == textLen || !text[i].isLetter()) continue; + + /* Highlight Types */ + i = applyCodeFormat(i, types, text, formatType); + /************************************************ + next letter is usually a space, in that case + going forward is useless, so continue; + ************************************************/ + if (i == textLen || !text[i].isLetter()) continue; + + /* Highlight Keywords */ + i = applyCodeFormat(i, keywords, text, formatKeyword); + if (i == textLen || !text[i].isLetter()) continue; + + /* Highlight Literals (true/false/NULL,nullptr) */ + i = applyCodeFormat(i, literals, text, formatNumLit); + if (i == textLen || !text[i].isLetter()) continue; + + /* Highlight Builtin library stuff */ + i = applyCodeFormat(i, builtin, text, formatBuiltIn); + if (i == textLen || !text[i].isLetter()) continue; + + /* Highlight other stuff (preprocessor etc.) */ + if (i == 0 || !text.at(i - 1).isLetter()) { + const char c = text.at(i).toLatin1(); + auto it = others.find(c); + for (; it != others.end() && it.key() == c; ++it) { + const QLatin1String &word = it.value(); + if (word == MH_SUBSTR(i, word.size()) && + (i + word.size() == text.length() || + !text.at(i + word.size()).isLetter())) { + currentBlockState() == CodeCpp || + currentBlockState() == CodeC + ? setFormat(i - 1, word.size() + 1, formatOther) + : setFormat(i, word.size(), formatOther); + i += word.size(); + } + } + } + + // we were unable to find any match, lets skip this word + if (pos == i) { + int cnt = i; + while (cnt < textLen) { + if (!text[cnt].isLetter()) break; + ++cnt; + } + i = cnt - 1; + } + } + + /*********************** + **** POST PROCESSORS *** + ***********************/ + + if (isCSS) cssHighlighter(text); + if (isYAML) ymlHighlighter(text); + if (isMake) makeHighlighter(text); + if (isForth) forthHighlighter(text); + if (isGDScript) gdscriptHighlighter(text); + if (isSQL) sqlHighlighter(text); + if (isTOML) tomlHighlighter(text); +} + +/** + * @brief Highlight string literals in code + * @param strType str type i.e., ' or " + * @param text the text being scanned + * @param i pos of i in loop + * @return pos of i after the string + */ +int MarkdownHighlighter::highlightStringLiterals(QChar strType, + const QString &text, int i) { + const auto &strFormat = _formats[CodeString]; + setFormat(i, 1, strFormat); + ++i; + + while (i < text.length()) { + // look for string end + // make sure it's not an escape seq + if (text.at(i) == strType && text.at(i - 1) != QLatin1Char('\\')) { + setFormat(i, 1, strFormat); + ++i; + break; + } + // look for escape sequence + if (text.at(i) == QLatin1Char('\\') && (i + 1) < text.length()) { + int len = 0; + switch (text.at(i + 1).toLatin1()) { + case 'a': + case 'b': + case 'e': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '\'': + case '"': + case '\\': + case '\?': + // 2 because we have to highlight \ as well as the following + // char + len = 2; + break; + // octal esc sequence \123 + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { + if (i + 4 <= text.length()) { + if (!isOctal(text.at(i + 2).toLatin1())) { + break; + } + if (!isOctal(text.at(i + 3).toLatin1())) { + break; + } + len = 4; + } + break; + } + // hex numbers \xFA + case 'x': { + if (i + 3 <= text.length()) { + if (!isHex(text.at(i + 2).toLatin1())) { + break; + } + if (!isHex(text.at(i + 3).toLatin1())) { + break; + } + len = 4; + } + break; + } + // TODO: implement Unicode code point escaping + default: + break; + } + + // if len is zero, that means this wasn't an esc seq + // increment i so that we skip this backslash + if (len == 0) { + setFormat(i, 1, strFormat); + ++i; + continue; + } + + setFormat(i, len, _formats[CodeNumLiteral]); + i += len; + continue; + } + setFormat(i, 1, strFormat); + ++i; + } + return i - 1; +} + +/** + * @brief Highlight numeric literals in code + * @param text the text being scanned + * @param i pos of i in loop + * @return pos of i after the number + * + * @details it doesn't highlight the following yet: + * - 1000'0000 + */ +int MarkdownHighlighter::highlightNumericLiterals(const QString &text, int i) { + bool isPrefixAllowed = false; + if (i == 0) { + isPrefixAllowed = true; + } else { + // these values are allowed before a number + switch (text.at(i - 1).toLatin1()) { + // CSS number + case ':': + if (currentBlockState() == CodeCSS) { + isPrefixAllowed = true; + } + break; + case '[': + case '(': + case '{': + case ' ': + case ',': + case '=': + case '+': + case '-': + case '*': + case '/': + case '%': + case '<': + case '>': + isPrefixAllowed = true; + break; + } + } + + if (!isPrefixAllowed) return i; + + const int start = i; + + if ((i + 1) >= text.length()) { + setFormat(i, 1, _formats[CodeNumLiteral]); + return ++i; + } + + ++i; + // hex numbers highlighting (only if there's a preceding zero) + bool isCurrentHex = false; + if (text.at(i) == QChar('x') && text.at(i - 1) == QChar('0')) { + isCurrentHex = true; + ++i; + } + + while (i < text.length()) { + if (!text.at(i).isNumber() && text.at(i) != QChar('.') && + text.at(i) != QChar('e') && + !(isCurrentHex && isHex(text.at(i).toLatin1()))) + break; + ++i; + } + + bool isPostfixAllowed = false; + if (i == text.length()) { + // cant have e at the end + if (isCurrentHex || text.at(i - 1) != QChar('e')) { + isPostfixAllowed = true; + } + } else { + // these values are allowed after a number + switch (text.at(i).toLatin1()) { + case ']': + case ')': + case '}': + case ' ': + case ',': + case '=': + case '+': + case '-': + case '*': + case '/': + case '%': + case '>': + case '<': + case ';': + isPostfixAllowed = true; + break; + // for 100u, 1.0F + case 'p': + if (currentBlockState() == CodeCSS) { + if (i + 1 < text.length() && text.at(i + 1) == QChar('x')) { + if (i + 2 == text.length() || + !text.at(i + 2).isLetterOrNumber()) { + isPostfixAllowed = true; + } + } + } + break; + case 'e': + if (currentBlockState() == CodeCSS) { + if (i + 1 < text.length() && text.at(i + 1) == QChar('m')) { + if (i + 2 == text.length() || + !text.at(i + 2).isLetterOrNumber()) { + isPostfixAllowed = true; + } + } + } + break; + case 'u': + case 'l': + case 'f': + case 'U': + case 'L': + case 'F': + if (i + 1 == text.length() || + !text.at(i + 1).isLetterOrNumber()) { + isPostfixAllowed = true; + ++i; + } + break; + } + } + if (isPostfixAllowed) { + int end = i--; + setFormat(start, end - start, _formats[CodeNumLiteral]); + } + // decrement so that the index is at the last number, not after it + return i; +} + +/** + * @brief The Tagger Script highlighter + * @param text + * @details his function is responsible for taggerscript highlighting. + * It highlights anything between a (inclusive) '&' and a (exclusive) '(' as a + * function. An exception is the '$noop()'function, which get highlighted as a + * comment. + * + * It has basic error detection when there is an unlcosed %Metadata Variable% + */ +void MarkdownHighlighter::taggerScriptHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + + for (int i = 0; i < textLen; ++i) { + // highlight functions, unless it's a comment function + if (text.at(i) == QChar('$') && + MH_SUBSTR(i, 5) != QLatin1String("$noop")) { + const int next = text.indexOf(QChar('('), i); + if (next == -1) break; + setFormat(i, next - i, _formats[CodeKeyWord]); + i = next; + } + + // highlight variables + if (text.at(i) == QChar('%')) { + const int next = text.indexOf(QChar('%'), i + 1); + const int start = i; + i++; + if (next != -1) { + setFormat(start, next - start + 1, _formats[CodeType]); + } else { + // error highlighting + QTextCharFormat errorFormat = _formats[NoState]; + errorFormat.setUnderlineColor(Qt::red); + errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); + setFormat(start, 1, errorFormat); + } + } + + // highlight comments + if (MH_SUBSTR(i, 5) == QLatin1String("$noop")) { + const int next = text.indexOf(QChar(')'), i); + if (next == -1) break; + setFormat(i, next - i + 1, _formats[CodeComment]); + i = next; + } + + // highlight escape chars + if (text.at(i) == QChar('\\')) { + setFormat(i, 2, _formats[CodeOther]); + i++; + } + } +} + +/** + * @brief The YAML highlighter + * @param text + * @details This function post processes a line after the main syntax + * highlighter has run for additional highlighting. It does these things + * + * If the current line is a comment, skip it + * + * Highlight all the words that have a colon after them as 'keyword' except: + * If the word is a string, skip it. + * If the colon is in between a path, skip it (C:\) + * + * Once the colon is found, the function will skip every character except 'h' + * + * If an h letter is found, check the next 4/5 letters for http/https and + * highlight them as a link (underlined) + */ +void MarkdownHighlighter::ymlHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + bool colonNotFound = false; + + // if this is a comment don't do anything and just return + if (text.trimmed().at(0) == QChar('#')) return; + + for (int i = 0; i < textLen; ++i) { + if (!text.at(i).isLetter()) continue; + + if (colonNotFound && text.at(i) != QChar('h')) continue; + + // we found a string literal, skip it + if (i != 0 && text.at(i - 1) == QChar('"')) { + const int next = text.indexOf(QChar('"'), i); + if (next == -1) break; + i = next; + continue; + } + + if (i != 0 && text.at(i - 1) == QChar('\'')) { + const int next = text.indexOf(QChar('\''), i); + if (next == -1) break; + i = next; + continue; + } + + const int colon = text.indexOf(QChar(':'), i); + + // if colon isn't found, we set this true + if (colon == -1) colonNotFound = true; + + if (!colonNotFound) { + // if the line ends here, format and return + if (colon + 1 == textLen) { + setFormat(i, colon - i, _formats[CodeKeyWord]); + return; + } + // colon is found, check if it isn't some path or something else + if (!(text.at(colon + 1) == QChar('\\') && + text.at(colon + 1) == QChar('/'))) { + setFormat(i, colon - i, _formats[CodeKeyWord]); + } + } + + // underlined links + if (text.at(i) == QChar('h')) { + if (MH_SUBSTR(i, 4) == QLatin1String("http")) { + int space = text.indexOf(QChar(' '), i); + if (space == -1) space = textLen; + QTextCharFormat f = _formats[CodeString]; + f.setUnderlineStyle(QTextCharFormat::SingleUnderline); + setFormat(i, space - i, f); + i = space; + } + } + } +} + +/** + * @brief The INI highlighter + * @param text The text being highlighted + * @details This function is responsible for ini highlighting. + * It has basic error detection when + * (1) You opened a section but didn't close with bracket e.g [Section + * (2) You wrote an option but it didn't have an '=' + * Such errors will be marked with a dotted red underline + * + * It has comment highlighting support. Everything after a ';' will + * be highlighted till the end of the line. + * + * An option value pair will be highlighted regardless of space. Example: + * Option 1 = value + * In this, 'Option 1' will be highlighted completely and not just '1'. + * I am not sure about its correctness but for now its like this. + * + * The loop is unrolled frequently upon a match. Before adding anything + * new be sure to test in debug mode and apply bound checking as required. + */ +void MarkdownHighlighter::iniHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + + for (int i = 0; i < textLen; ++i) { + // start of a [section] + if (text.at(i) == QChar('[')) { + QTextCharFormat sectionFormat = _formats[CodeType]; + int sectionEnd = text.indexOf(QChar(']'), i); + // if an end bracket isn't found, we apply red underline to show + // error + if (sectionEnd == -1) { + sectionFormat.setUnderlineStyle(QTextCharFormat::DotLine); + sectionFormat.setUnderlineColor(Qt::red); + sectionEnd = textLen; + } + sectionEnd++; + setFormat(i, sectionEnd - i, sectionFormat); + i = sectionEnd; + if (i >= textLen) break; + } + + // comment ';' + else if (text.at(i) == QChar(';')) { + setFormat(i, textLen - i, _formats[CodeComment]); + i = textLen; + break; + } + + // key-val + else if (text.at(i).isLetter()) { + QTextCharFormat format = _formats[CodeKeyWord]; + int equalsPos = text.indexOf(QChar('='), i); + if (equalsPos == -1) { + format.setUnderlineColor(Qt::red); + format.setUnderlineStyle(QTextCharFormat::DotLine); + equalsPos = textLen; + } + setFormat(i, equalsPos - i, format); + i = equalsPos - 1; + if (i >= textLen) break; + } + // skip everything after '=' (except comment) + else if (text.at(i) == QChar('=')) { + const int findComment = text.indexOf(QChar(';'), i); + if (findComment == -1) break; + i = findComment - 1; + } + } +} + +void MarkdownHighlighter::cssHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + for (int i = 0; i < textLen; ++i) { + if (text[i] == QLatin1Char('.') || text[i] == QLatin1Char('#')) { + if (i + 1 >= textLen) return; + if (text[i + 1].isSpace() || text[i + 1].isNumber()) continue; + int space = text.indexOf(QLatin1Char(' '), i); + if (space < 0) { + space = text.indexOf(QLatin1Char('{'), i); + if (space < 0) { + space = textLen; + } + } + setFormat(i, space - i, _formats[CodeKeyWord]); + i = space; + } else if (text[i] == QLatin1Char('c')) { + if (MH_SUBSTR(i, 5) == QLatin1String("color")) { + i += 5; + const int colon = text.indexOf(QLatin1Char(':'), i); + if (colon < 0) continue; + i = colon; + ++i; + while (i < textLen) { + if (!text[i].isSpace()) break; + ++i; + } + int semicolon = text.indexOf(QLatin1Char(';'), i); + if (semicolon < 0) semicolon = textLen; + const QString color = text.mid(i, semicolon - i); + QColor c(color); + if (color.startsWith(QLatin1String("rgb"))) { + const int t = text.indexOf(QLatin1Char('('), i); + const int rPos = text.indexOf(QLatin1Char(','), t); + const int gPos = text.indexOf(QLatin1Char(','), rPos + 1); + const int bPos = text.indexOf(QLatin1Char(')'), gPos); + if (rPos > -1 && gPos > -1 && bPos > -1) { + const QString r = text.mid(t + 1, rPos - (t + 1)); + const QString g = text.mid(rPos + 1, gPos - (rPos + 1)); + const QString b = text.mid(gPos + 1, bPos - (gPos + 1)); + c.setRgb(r.toInt(), g.toInt(), b.toInt()); + } else { + c = _formats[HighlighterState::NoState] + .background() + .color(); + } + } + + if (!c.isValid()) { + continue; + } + + int lightness{}; + QColor foreground; + // really dark + if (c.lightness() <= 20) { + foreground = Qt::white; + } else if (c.lightness() > 20 && c.lightness() <= 51) { + foreground = QColor(204, 204, 204); + } else if (c.lightness() > 51 && c.lightness() <= 110) { + foreground = QColor(187, 187, 187); + } else if (c.lightness() > 127) { + lightness = c.lightness() + 100; + foreground = c.darker(lightness); + } else { + lightness = c.lightness() + 100; + foreground = c.lighter(lightness); + } + + QTextCharFormat f = _formats[CodeBlock]; + f.setBackground(c); + f.setForeground(foreground); + // clear prev format + setFormat(i, semicolon - i, QTextCharFormat()); + setFormat(i, semicolon - i, f); + i = semicolon; + } + } + } +} + +void MarkdownHighlighter::xmlHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + + setFormat(0, textLen, _formats[CodeBlock]); + + for (int i = 0; i < textLen; ++i) { + if (i + 1 < textLen && text[i] == QLatin1Char('<') && + text[i + 1] != QLatin1Char('!')) { + const int found = text.indexOf(QLatin1Char('>'), i); + if (found > 0) { + ++i; + if (text[i] == QLatin1Char('/')) ++i; + setFormat(i, found - i, _formats[CodeKeyWord]); + } + } + + if (text[i] == QLatin1Char('=')) { + int lastSpace = text.lastIndexOf(QLatin1Char(' '), i); + if (lastSpace == i - 1) + lastSpace = text.lastIndexOf(QLatin1Char(' '), i - 2); + if (lastSpace > 0) { + setFormat(lastSpace, i - lastSpace, _formats[CodeBuiltIn]); + } + } + + if (text[i] == QLatin1Char('\"')) { + const int pos = i; + int cnt = 1; + ++i; + // bound check + if ((i + 1) >= textLen) return; + while (i < textLen) { + if (text[i] == QLatin1Char('\"')) { + ++cnt; + ++i; + break; + } + ++i; + ++cnt; + // bound check + if ((i + 1) >= textLen) { + ++cnt; + break; + } + } + setFormat(pos, cnt, _formats[CodeString]); + } + } +} + +void MarkdownHighlighter::makeHighlighter(const QString &text) { + const int colonPos = text.indexOf(QLatin1Char(':')); + if (colonPos == -1) return; + setFormat(0, colonPos, _formats[CodeBuiltIn]); +} + +/** + * @brief The Forth highlighter + * @param text + * @details This function performs filtering of Forth code and high lights + * the specific details. + * 1. It highlights the "\ " comments + * 2. It highlights the "( " comments + */ +void MarkdownHighlighter::forthHighlighter(const QString &text) { + if (text.isEmpty()) return; + + const auto textLen = text.length(); + + // Default Format + setFormat(0, textLen, _formats[CodeBlock]); + + for (int i = 0; i < textLen; ++i) { + // 1, It highlights the "\ " comments + if (i + 1 <= textLen && text[i] == QLatin1Char('\\') && + text[i + 1] == QLatin1Char(' ')) { + // The full line is commented + setFormat(i + 1, textLen - 1, _formats[CodeComment]); + break; + } + // 2. It highlights the "( " comments + else if (i + 1 <= textLen && text[i] == QLatin1Char('(') && + text[i + 1] == QLatin1Char(' ')) { + // Find the End bracket + int lastBracket = text.lastIndexOf(QLatin1Char(')'), i); + // Can't Handle wrong Format + if (lastBracket <= 0) return; + // ' )' at the end of the comment + if (lastBracket <= textLen && + text[lastBracket] == QLatin1Char(' ')) { + setFormat(i, lastBracket, _formats[CodeComment]); + } + } + } +} + +/** + * @brief The GDScript highlighter + * @param text + * @details This function is responsible for GDScript highlighting. + * 1. Hightlight '$' NodePath constructs. + * 2. Highlight '%' UniqueNode constructs. + * 3. Highlight '@' annotations as `CodeOther` + */ +void MarkdownHighlighter::gdscriptHighlighter(const QString &text) { + if (text.isEmpty()) return; + + // 1. Hightlight '$' NodePath constructs. + // 2. Highlight '%' UniqueNode constructs. + const QRegularExpression re = QRegularExpression(QStringLiteral( + R"([$%][a-zA-Z_][a-zA-Z0-9_]*(/[a-zA-Z_][a-zA-Z0-9_]*)*|@)")); + QRegularExpressionMatchIterator i = re.globalMatch(text); + while (i.hasNext()) { + QRegularExpressionMatch match = i.next(); + // 3. Hightlight '@' annotation symbol + if (match.captured().startsWith(QLatin1Char('@'))) { + setFormat(match.capturedStart(), match.capturedLength(), + _formats[CodeOther]); + } else { + setFormat(match.capturedStart(), match.capturedLength(), + _formats[CodeNumLiteral]); + } + } +} + +/** + * @brief The SQL highlighter + * @param text + * @details This function is responsible for SQL comment highlighting. + * 1. Highlight "--" comments + * 2. Highlight "/ *"-style multi-line comments + */ +void MarkdownHighlighter::sqlHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + + for (int i = 0; i < textLen; ++i) { + if (i + 1 > textLen) { + break; + } + // Check for comments: single-line, or multi-line start or end + if (text[i] == QLatin1Char('-') && text[i + 1] == QLatin1Char('-')) { + setFormat(i, textLen, _formats[CodeComment]); + } else if (text[i] == QLatin1Char('/') && + text[i + 1] == QLatin1Char('*')) { + // we're in a multi-line comment now + if (currentBlockState() % 2 == 0) { + setCurrentBlockState(currentBlockState() + 1); + // Did the multi-line comment end in the same line? + int endingComment = text.indexOf(QLatin1String("*/"), i + 2); + int highlightEnd = textLen; + if (endingComment > -1) { + highlightEnd = endingComment + 2; + } + + setFormat(i, highlightEnd - i, _formats[CodeComment]); + } + } else if (text[i] == QLatin1Char('*') && + text[i + 1] == QLatin1Char('/')) { + // we're now no longer in a multi-line comment + if (currentBlockState() % 2 != 0) { + setCurrentBlockState(currentBlockState() - 1); + // Did the multi-line comment start in the same line? + int startingComment = text.indexOf(QLatin1String("/*"), 0); + int highlightStart = 0; + if (startingComment > -1) { + highlightStart = startingComment; + } + + setFormat(highlightStart - i, i + 1, _formats[CodeComment]); + } + } + } +} + +/** + * @brief The TOML highlighter + * @param text + * @details This function is responsible for TOML highlighting. + */ +void MarkdownHighlighter::tomlHighlighter(const QString &text) { + if (text.isEmpty()) return; + const auto textLen = text.length(); + + bool onlyWhitespaceBeforeHeader = true; + int possibleAssignmentPos = text.indexOf(QLatin1Char('='), 0); + int singleQStringStart = -1; + int doubleQStringStart = -1; + int multiSingleQStringStart = -1; + int multiDoubleQStringStart = -1; + QLatin1Char singleQ = QLatin1Char('\''); + QLatin1Char doubleQ = QLatin1Char('"'); + + for (int i = 0; i < textLen; ++i) { + if (i + 1 > textLen) { + break; + } + + // track the state of strings + // multiline highlighting doesn't quite behave due to clashing handling + // of " and ' chars, but this accomodates normal " and ' strings, as + // well as ones wrapped by either """ or ''' + if (text[i] == doubleQ) { + if (i + 2 <= textLen && text[i + 1] == doubleQ && + text[i + 2] == doubleQ) { + if (multiDoubleQStringStart > -1) { + multiDoubleQStringStart = -1; + } else { + multiDoubleQStringStart = i; + int multiDoubleQStringEnd = + text.indexOf(QLatin1String("\"\"\""), i + 1); + if (multiDoubleQStringEnd > -1) { + setFormat(i, multiDoubleQStringEnd - i, + _formats[CodeString]); + i = multiDoubleQStringEnd + 2; + multiDoubleQStringEnd = -1; + multiDoubleQStringStart = -1; + continue; + } + } + } else { + if (doubleQStringStart > -1) { + doubleQStringStart = -1; + } else { + doubleQStringStart = i; + } + } + } else if (text[i] == singleQ) { + if (i + 2 <= textLen && text[i + 1] == singleQ && + text[i + 2] == singleQ) { + if (multiSingleQStringStart > -1) { + multiSingleQStringStart = -1; + } else { + multiSingleQStringStart = i; + int multiSingleQStringEnd = + text.indexOf(QLatin1String("'''"), i + 1); + if (multiSingleQStringEnd > -1) { + setFormat(i, multiSingleQStringEnd - i, + _formats[CodeString]); + i = multiSingleQStringEnd + 2; + multiSingleQStringEnd = -1; + multiSingleQStringStart = -1; + continue; + } + } + } else { + if (singleQStringStart > -1) { + singleQStringStart = -1; + } else { + singleQStringStart = i; + } + } + } + + bool inString = doubleQStringStart > -1 || singleQStringStart > -1 || + multiSingleQStringStart > -1 || + multiDoubleQStringStart > -1; + + // do comment highlighting + if (text[i] == QLatin1Char('#') && !inString) { + setFormat(i, textLen - i, _formats[CodeComment]); + return; + } + + // table header (all stuff preceeding must only be whitespace) + if (text[i] == QLatin1Char('[') && onlyWhitespaceBeforeHeader) { + int headerEnd = text.indexOf(QLatin1Char(']'), i); + if (headerEnd > -1) { + setFormat(i, headerEnd + 1 - i, _formats[CodeType]); + return; + } + } + + // handle numbers, inf, nan and datetime the same way + if (i > possibleAssignmentPos && !inString && + (text[i].isNumber() || text.indexOf(QLatin1String("inf"), i) > 0 || + text.indexOf(QLatin1String("nan"), i) > 0)) { + int nextWhitespace = text.indexOf(QLatin1Char(' '), i); + int endOfNumber = textLen; + if (nextWhitespace > -1) { + if (text[nextWhitespace - 1] == QLatin1Char(',')) + nextWhitespace--; + endOfNumber = nextWhitespace; + } + + int highlightStart = i; + if (i > 0) { + if (text[i - 1] == QLatin1Char('-') || + text[i - 1] == QLatin1Char('+')) { + highlightStart--; + } + } + setFormat(highlightStart, endOfNumber - highlightStart, + _formats[CodeNumLiteral]); + i = endOfNumber; + } + + if (!text[i].isSpace()) { + onlyWhitespaceBeforeHeader = false; + } + } +} + +/** + * Highlight multi-line frontmatter blocks + * + * @param text + */ +void MarkdownHighlighter::highlightFrontmatterBlock(const QString &text) { + if (text == QLatin1String("---")) { + const bool foundEnd = + previousBlockState() == HighlighterState::FrontmatterBlock; + + // return if the frontmatter block was already highlighted in previous + // blocks, there just can be one frontmatter block + if (!foundEnd && document()->firstBlock() != currentBlock()) { + return; + } + + setCurrentBlockState(foundEnd ? HighlighterState::FrontmatterBlockEnd + : HighlighterState::FrontmatterBlock); + + QTextCharFormat &maskedFormat = + _formats[HighlighterState::MaskedSyntax]; + setFormat(0, text.length(), maskedFormat); + } else if (previousBlockState() == HighlighterState::FrontmatterBlock) { + setCurrentBlockState(HighlighterState::FrontmatterBlock); + setFormat(0, text.length(), _formats[HighlighterState::MaskedSyntax]); } } @@ -612,29 +1964,173 @@ void MarkdownHighlighter::highlightCodeBlock(QString text) { * * @param text */ -void MarkdownHighlighter::highlightCommentBlock(QString text) { - bool highlight = false; - text = text.trimmed(); - QString startText = ""; +void MarkdownHighlighter::highlightCommentBlock(const QString &text) { + if (text.startsWith(QLatin1String(" ")) || + text.startsWith(QLatin1Char('\t'))) + return; + + const QString &trimmedText = text.trimmed(); + const QString startText(QStringLiteral("")); // we will skip this case because that is an inline comment and causes // troubles here - if (text.startsWith(startText) && text.contains(endText)) { + if (trimmedText.startsWith(startText) && trimmedText.contains(endText)) { return; } - if (text.startsWith(startText) || - (!text.endsWith(endText) && - (previousBlockState() == HighlighterState::Comment))) { - setCurrentBlockState(HighlighterState::Comment); - highlight = true; - } else if (text.endsWith(endText)) { - highlight = true; + if (!trimmedText.startsWith(startText) && trimmedText.contains(startText)) + return; + + const bool isComment = + trimmedText.startsWith(startText) || + (!trimmedText.endsWith(endText) && previousBlockState() == Comment); + const bool isCommentEnd = + trimmedText.endsWith(endText) && previousBlockState() == Comment; + const bool highlight = isComment || isCommentEnd; + + if (isComment) setCurrentBlockState(Comment); + if (highlight) setFormat(0, text.length(), _formats[Comment]); +} + +/** + * @brief Highlights thematic breaks i.e., horizontal ruler
+ * @param text + */ +void MarkdownHighlighter::highlightThematicBreak(const QString &text) { + int i = 0; + for (; i < 4 && i < text.length(); ++i) { + if (text.at(i) != QLatin1Char(' ')) break; } - if (highlight) { - setFormat(0, text.length(), _formats[HighlighterState::Comment]); + const QString sText = text.mid(i); + if (sText.isEmpty() || i == 4 || text.startsWith(QLatin1Char('\t'))) return; + + const char c = sText.at(0).toLatin1(); + if (c != '-' && c != '_' && c != '*') return; + + int len = 0; + bool hasSameChars = true; + for (int i = 0; i < sText.length(); ++i) { + if (c != sText.at(i) && sText.at(i) != QLatin1Char(' ')) { + hasSameChars = false; + break; + } + if (sText.at(i) != QLatin1Char(' ')) ++len; + } + if (len < 3) return; + + if (hasSameChars) setFormat(0, text.length(), _formats[HorizontalRuler]); +} + +void MarkdownHighlighter::highlightCheckbox(const QString &text, int curPos) { + if (curPos + 4 >= text.length()) return; + + const bool hasOpeningBracket = text.at(curPos + 2) == QLatin1Char('['); + const bool hasClosingBracket = text.at(curPos + 4) == QLatin1Char(']'); + const QChar midChar = text.at(curPos + 3); + const bool hasXorSpace = midChar == QLatin1Char(' ') || + midChar == QLatin1Char('x') || + midChar == QLatin1Char('X'); + const bool hasDash = midChar == QLatin1Char('-'); + + if (hasOpeningBracket && hasClosingBracket && (hasXorSpace || hasDash)) { + const int start = curPos + 2; + constexpr int length = 3; + + const auto fmt = hasXorSpace + ? (midChar == QLatin1Char(' ') ? CheckBoxUnChecked + : CheckBoxChecked) + : MaskedSyntax; + + setFormat(start, length, _formats[fmt]); + } +} + +static bool isBeginningOfList(QChar front) { + return front == QLatin1Char('-') || front == QLatin1Char('+') || + front == QLatin1Char('*') || front.isNumber(); +} + +/** + * @brief Highlight lists in markdown + * @param text - current text block + */ +void MarkdownHighlighter::highlightLists(const QString &text) { + int spaces = 0; + // Skip any spaces in the beginning + while (spaces < text.length() && text.at(spaces).isSpace()) ++spaces; + + // return if we reached the end + if (spaces >= text.length()) return; + + const QChar front = text.at(spaces); + // check for start of list + if (!isBeginningOfList(front)) { + return; + } + + const int curPos = spaces; + + // Ordered List + if (front.isNumber()) { + int number = curPos; + // move forward till first non-number char + while (number < text.length() && text.at(number).isNumber()) ++number; + int count = number - curPos; + + // reached end? + if (number + 1 >= text.length() || count > 9) return; + + // there should be a '.' or ')' after a number + if ((text.at(number) == QLatin1Char('.') || + text.at(number) == QLatin1Char(')')) && + (text.at(number + 1) == QLatin1Char(' '))) { + setCurrentBlockState(List); + setFormat(curPos, number - curPos + 1, _formats[List]); + + // highlight checkbox if any + highlightCheckbox(text, number); + } + + return; + } + + // if its just a '-' etc, no highlighting + if (curPos + 1 >= text.length()) return; + + // check for a space after it + if (text.at(curPos + 1) != QLatin1Char(' ')) return; + + // check if we are in checkbox list + highlightCheckbox(text, curPos); + + /* Unordered List */ + setCurrentBlockState(List); + setFormat(curPos, 1, _formats[List]); +} + +/** + * Format italics, bolds and links in headings(h1-h6) + * + * @param format The format that is being applied + * @param match The regex match + * @param capturedGroup The captured group + */ +void MarkdownHighlighter::setHeadingStyles(HighlighterState rule, + const QRegularExpressionMatch &match, + const int capturedGroup) { + auto state = static_cast(currentBlockState()); + const QTextCharFormat &f = _formats[state]; + + if (rule == HighlighterState::Link) { + auto linkFmt = _formats[Link]; + linkFmt.setFontPointSize(f.fontPointSize()); + if (capturedGroup == 1) { + setFormat(match.capturedStart(capturedGroup), + match.capturedLength(capturedGroup), linkFmt); + } + return; } } @@ -644,55 +2140,782 @@ void MarkdownHighlighter::highlightCommentBlock(QString text) { * @param text */ void MarkdownHighlighter::highlightAdditionalRules( - QVector &rules, QString text) { - QTextCharFormat &maskedFormat = _formats[HighlighterState::MaskedSyntax]; + const QVector &rules, const QString &text) { + const auto &maskedFormat = _formats[HighlighterState::MaskedSyntax]; - for(const HighlightingRule &rule : rules) { - // continue if an other current block state was already set if - // disableIfCurrentStateIsSet is set - if (rule.disableIfCurrentStateIsSet && - (currentBlockState() != HighlighterState::NoState)) { - continue; - } + for (const HighlightingRule &rule : rules) { + // continue if another current block state was already set if + // disableIfCurrentStateIsSet is set + if (currentBlockState() != NoState) continue; - QRegularExpression expression(rule.pattern); - QRegularExpressionMatchIterator iterator = expression.globalMatch(text); - int capturingGroup = rule.capturingGroup; - int maskedGroup = rule.maskedGroup; - QTextCharFormat &format = _formats[rule.state]; + const bool contains = text.contains(rule.shouldContain); + if (!contains) continue; - // store the current block state if useStateAsCurrentBlockState - // is set - if (iterator.hasNext() && rule.useStateAsCurrentBlockState) { - setCurrentBlockState(rule.state); - } + auto iterator = rule.pattern.globalMatch(text); + const uint8_t capturingGroup = rule.capturingGroup; + const uint8_t maskedGroup = rule.maskedGroup; + const QTextCharFormat &format = _formats[rule.state]; - // find and format all occurrences - while (iterator.hasNext()) { - QRegularExpressionMatch match = iterator.next(); + // find and format all occurrences + while (iterator.hasNext()) { + QRegularExpressionMatch match = iterator.next(); - // if there is a capturingGroup set then first highlight - // everything as MaskedSyntax and highlight capturingGroup - // with the real format - if (capturingGroup > 0) { - QTextCharFormat currentMaskedFormat = maskedFormat; - // set the font size from the current rule's font format - if (format.fontPointSize() > 0) { - currentMaskedFormat.setFontPointSize(format.fontPointSize()); - } + // if there is a capturingGroup set then first highlight + // everything as MaskedSyntax and highlight capturingGroup + // with the real format + if (capturingGroup > 0) { + QTextCharFormat currentMaskedFormat = maskedFormat; + // set the font size from the current rule's font format + if (format.fontPointSize() > 0) { + currentMaskedFormat.setFontPointSize( + format.fontPointSize()); + } + if (isHeading(currentBlockState())) { + // setHeadingStyles(format, match, maskedGroup); + + } else { setFormat(match.capturedStart(maskedGroup), match.capturedLength(maskedGroup), currentMaskedFormat); } + } + if (isHeading(currentBlockState())) { + setHeadingStyles(rule.state, match, capturingGroup); + } else { setFormat(match.capturedStart(capturingGroup), - match.capturedLength(capturingGroup), - format); + match.capturedLength(capturingGroup), format); } } + } } -void MarkdownHighlighter::setHighlightingOptions(HighlightingOptions options) { +/** + * @brief helper function to check if we are in a link while highlighting inline + * rules + * @param pos + * @param range + */ +int isInLinkRange(int pos, QVector> &range) { + int j = 0; + for (const auto &i : range) { + if (pos >= i.first && pos <= i.second) { + // return the length of the range so that we can skip it + const int len = i.second - i.first; + range.remove(j); + return len; + } + ++j; + } + return -1; +} + +/** + * @brief highlight inline rules aka Emphasis, bolds, inline code spans, + * underlines, strikethrough, links, and images. + */ +void MarkdownHighlighter::highlightInlineRules(const QString &text) { + // clear existing span ranges for this block + auto it = _ranges.find(currentBlock().blockNumber()); + if (it != _ranges.end()) { + it->clear(); + } + + for (int i = 0; i < text.length(); ++i) { + QChar currentChar = text.at(i); + + if (currentChar == QLatin1Char('`') || + currentChar == QLatin1Char('~')) { + i = highlightInlineSpans(text, i, currentChar); + } else if (currentChar == QLatin1Char('<') && + MH_SUBSTR(i, 4) == QLatin1String(" + * @param text + * @param pos + * @return position after the comment + */ +int MarkdownHighlighter::highlightInlineComment(const QString &text, int pos) { + const int start = pos; + pos += 4; + + if (pos >= text.length()) return pos; + + int commentEnd = text.indexOf(QLatin1String("-->"), pos); + if (commentEnd == -1) return pos; + + commentEnd += 3; + setFormat(start, commentEnd - start, _formats[Comment]); + return commentEnd - 1; +} + +/**************************************** + * EM and Strong Parsing + Highlighting * + ****************************************/ + +struct Delimiter { + int pos; + int len; + int end; + int jump; + bool open; + bool close; + char marker; +}; + +inline bool isMDAsciiPunct(const int ch) noexcept { + return (ch >= 33 && ch <= 47) || (ch >= 58 && ch <= 64) || + (ch >= 91 && ch <= 96) || (ch >= 123 && ch <= 126); +} + +/** + * @brief scans a chain of '*' or '_' + * @param text: current text block + * @param start: current position in the text + * @param canSplitWord: is Underscore + * @return length, canOpen, canClose + * @details Helper function for Em and strong highlighting + */ +QPair> scanDelims(const QString &text, const int start, + const bool canSplitWord) { + int pos = start; + const int textLen = text.length(); + const QChar marker = text.at(start); + bool leftFlanking = true; + bool rightFlanking = true; + + const QChar lastChar = start > 0 ? text.at(start - 1) : QChar('\0'); + + while (pos < textLen && text.at(pos) == marker) ++pos; + const int length = pos - start; + + const QChar nextChar = pos + 1 < textLen ? text.at(pos) : QChar('\0'); + + const bool isLastPunct = + isMDAsciiPunct(lastChar.toLatin1()) || lastChar.isPunct(); + const bool isNextPunct = + isMDAsciiPunct(nextChar.toLatin1()) || nextChar.isPunct(); + // treat line end and start as whitespace + const bool isLastWhiteSpace = lastChar.isNull() ? true : lastChar.isSpace(); + const bool isNextWhiteSpace = nextChar.isNull() ? true : nextChar.isSpace(); + + if (isNextWhiteSpace) { + leftFlanking = false; + } else if (isNextPunct) { + if (!(isLastWhiteSpace || isLastPunct)) leftFlanking = false; + } + + if (isLastWhiteSpace) { + rightFlanking = false; + } else if (isLastPunct) { + if (!(isNextWhiteSpace || isNextPunct)) rightFlanking = false; + } + + // qDebug () << isNextWhiteSpace << marker; + // qDebug () << text << leftFlanking << rightFlanking << lastChar << + // nextChar; + + const bool canOpen = canSplitWord + ? leftFlanking + : leftFlanking && (!rightFlanking || isLastPunct); + const bool canClose = canSplitWord + ? rightFlanking + : rightFlanking && (!leftFlanking || isNextPunct); + + return QPair>{length, {canOpen, canClose}}; +} + +int collectEmDelims(const QString &text, int curPos, + QVector &delims) { + const char marker = text.at(curPos).toLatin1(); + const auto result = scanDelims(text, curPos, marker == '*'); + const int length = result.first; + const bool canOpen = result.second.first; + const bool canClose = result.second.second; + for (int i = 0; i < length; ++i) { + const Delimiter d = {curPos + i, length, -1, i, + canOpen, canClose, marker}; + delims.append(d); + } + return curPos + length; +} + +void balancePairs(QVector &delims) { + for (int i = 0; i < delims.length(); ++i) { + const auto &lastDelim = delims.at(i); + + if (!lastDelim.close) continue; + + int j = i - lastDelim.jump - 1; + + while (j >= 0) { + const auto &curDelim = delims.at(j); + if (curDelim.open && curDelim.marker == lastDelim.marker && + curDelim.end < 0) { + const bool oddMatch = (curDelim.close || lastDelim.open) && + curDelim.len != -1 && + lastDelim.len != -1 && + (curDelim.len + lastDelim.len) % 3 == 0; + if (!oddMatch) { + delims[i].jump = i - j; + delims[i].open = false; + delims[j].end = i; + delims[j].jump = 0; + break; + } + } + j -= curDelim.jump + 1; + } + } +} + +QPair MarkdownHighlighter::findPositionInRanges( + MarkdownHighlighter::RangeType type, int blockNum, int pos) const { + const QVector rangeList = _ranges.value(blockNum); + auto it = std::find_if( + rangeList.cbegin(), rangeList.cend(), + [pos, type](const InlineRange &range) { + if ((pos == range.begin || pos == range.end) && range.type == type) + return true; + return false; + }); + if (it == rangeList.cend()) return {-1, -1}; + return {it->begin, it->end}; +} + +bool MarkdownHighlighter::isPosInACodeSpan(int blockNumber, + int position) const { + const QVector rangeList = _ranges.value(blockNumber); + return std::find_if(rangeList.cbegin(), rangeList.cend(), + [position](const InlineRange &range) { + if (position > range.begin && + position < range.end && + range.type == RangeType::CodeSpan) + return true; + return false; + }) != rangeList.cend(); +} + +bool MarkdownHighlighter::isPosInALink(int blockNumber, int position) const { + const QVector rangeList = _ranges.value(blockNumber); + return std::find_if(rangeList.cbegin(), rangeList.cend(), + [position](const InlineRange &range) { + return position > range.begin && + position < range.end && + range.type == RangeType::Link; + }) != rangeList.cend(); +} + +QPair MarkdownHighlighter::getSpanRange( + MarkdownHighlighter::RangeType rangeType, int blockNumber, + int position) const { + const QVector rangeList = _ranges.value(blockNumber); + const auto it = + std::find_if(rangeList.cbegin(), rangeList.cend(), + [position, rangeType](const InlineRange &range) { + if (position > range.begin && position < range.end && + range.type == rangeType) + return true; + return false; + }); + + if (it == rangeList.cend()) { + return QPair(-1, -1); + } else { + return QPair(it->begin, it->end); + } +} + +/** + * @brief highlights Em/Strong in text editor + */ +void MarkdownHighlighter::highlightEmAndStrong(const QString &text, + const int pos) { + // 1. collect all em/strong delimiters + QVector delims; + for (int i = pos; i < text.length(); ++i) { + if (text.at(i) != QLatin1Char('_') && text.at(i) != QLatin1Char('*')) + continue; + + bool isInCodeSpan = isPosInACodeSpan(currentBlock().blockNumber(), i); + if (isInCodeSpan) continue; + + i = collectEmDelims(text, i, delims); + --i; + } + + // 2. Balance pairs + balancePairs(delims); + + // start,length -> helper for applying masking later + QVector> masked; + masked.reserve(delims.size() / 2); + + // 3. final processing & highlighting + for (int i = delims.length() - 1; i >= 0; --i) { + const auto &startDelim = delims.at(i); + if (startDelim.marker != QLatin1Char('_') && + startDelim.marker != QLatin1Char('*')) + continue; + if (startDelim.end == -1) continue; + + const auto &endDelim = delims.at(startDelim.end); + auto state = static_cast(currentBlockState()); + + const bool isStrong = + i > 0 && delims.at(i - 1).end == startDelim.end + 1 && + delims.at(i - 1).pos == startDelim.pos - 1 && + delims.at(startDelim.end + 1).pos == endDelim.pos + 1 && + delims.at(i - 1).marker == startDelim.marker; + if (isStrong) { + // qDebug () << "St: " << startDelim.pos << endDelim.pos; + // qDebug () << "St Txt: "<< text.mid(startDelim.pos, + // endDelim.pos - startDelim.pos); + int k = startDelim.pos; + while (text.at(k) == startDelim.marker) + ++k; // look for first letter after the delim chain + // per character highlighting + const int boldLen = endDelim.pos - startDelim.pos; + const bool underline = _highlightingOptions.testFlag(Underline) && + startDelim.marker == QLatin1Char('_'); + while (k != (startDelim.pos + boldLen)) { + QTextCharFormat fmt = QSyntaxHighlighter::format(k); +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) + fmt.setFontFamily(_formats[Bold].fontFamily()); +#else + const QStringList fontFamilies = + _formats[Bold].fontFamilies().toStringList(); + if (!fontFamilies.isEmpty()) fmt.setFontFamilies(fontFamilies); +#endif + + if (_formats[state].fontPointSize() > 0) + fmt.setFontPointSize(_formats[state].fontPointSize()); + + // if we are in plain text, use the format's specified color + if (fmt.foreground() == QTextCharFormat().foreground()) + fmt.setForeground(_formats[Bold].foreground()); + if (underline) { + fmt.setForeground(_formats[StUnderline].foreground()); + fmt.setFont(_formats[StUnderline].font()); + fmt.setFontUnderline(_formats[StUnderline].fontUnderline()); + } else if (_formats[Bold].font().bold()) + fmt.setFontWeight(QFont::Bold); + setFormat(k, 1, fmt); + ++k; + } + masked.append({startDelim.pos - 1, 2}); + masked.append({endDelim.pos, 2}); + + int block = currentBlock().blockNumber(); + _ranges[block].append(InlineRange(startDelim.pos, endDelim.pos + 1, + RangeType::Emphasis)); + _ranges[block].append(InlineRange(startDelim.pos - 1, endDelim.pos, + RangeType::Emphasis)); + --i; + } else { + // qDebug () << "Em: " << startDelim.pos << endDelim.pos; + // qDebug () << "Em Txt: " << text.mid(startDelim.pos, + // endDelim.pos - startDelim.pos); + int k = startDelim.pos; + while (text.at(k) == startDelim.marker) ++k; + const bool underline = _highlightingOptions.testFlag(Underline) && + startDelim.marker == QLatin1Char('_'); + const int itLen = endDelim.pos - startDelim.pos; + while (k != (startDelim.pos + itLen)) { + QTextCharFormat fmt = QSyntaxHighlighter::format(k); + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) + fmt.setFontFamily(_formats[Italic].fontFamily()); +#else + const QStringList fontFamilies = + _formats[Italic].fontFamilies().toStringList(); + if (!fontFamilies.isEmpty()) fmt.setFontFamilies(fontFamilies); +#endif + + if (_formats[state].fontPointSize() > 0) + fmt.setFontPointSize(_formats[state].fontPointSize()); + + if (fmt.foreground() == QTextCharFormat().foreground()) + fmt.setForeground(_formats[Italic].foreground()); + + if (underline) + fmt.setFontUnderline(_formats[StUnderline].fontUnderline()); + else + fmt.setFontItalic(_formats[Italic].fontItalic()); + setFormat(k, 1, fmt); + ++k; + } + masked.append({startDelim.pos, 1}); + masked.append({endDelim.pos, 1}); + + int block = currentBlock().blockNumber(); + _ranges[block].append( + InlineRange(startDelim.pos, endDelim.pos, RangeType::Emphasis)); + } + } + + // 4. Apply masked syntax + for (int i = 0; i < masked.length(); ++i) { + QTextCharFormat maskedFmt = _formats[MaskedSyntax]; + auto state = static_cast(currentBlockState()); + if (_formats[state].fontPointSize() > 0) + maskedFmt.setFontPointSize(_formats[state].fontPointSize()); + setFormat(masked.at(i).first, masked.at(i).second, maskedFmt); + } +} + +void MarkdownHighlighter::setHighlightingOptions( + const HighlightingOptions options) { _highlightingOptions = options; } + +#undef MH_SUBSTR diff --git a/client/qmarkdowntextedit/markdownhighlighter.h b/client/qmarkdowntextedit/markdownhighlighter.h index e66f86f..cc0f103 100644 --- a/client/qmarkdowntextedit/markdownhighlighter.h +++ b/client/qmarkdowntextedit/markdownhighlighter.h @@ -1,52 +1,127 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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: * - * QPlainTextEdit markdown highlighter + * The above copyright notice and this permission notice 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. + * + * QPlainTextEdit Markdown highlighter */ - #pragma once -#include -#include #include +#include +#include + +#ifdef QT_QUICK_LIB +#include +#endif QT_BEGIN_NAMESPACE class QTextDocument; QT_END_NAMESPACE -class MarkdownHighlighter : public QSyntaxHighlighter -{ -Q_OBJECT +class MarkdownHighlighter : public QSyntaxHighlighter { + Q_OBJECT -public: - enum HighlightingOption{ +#ifdef QT_QUICK_LIB + Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument WRITE + setTextDocument NOTIFY textDocumentChanged) + + QQuickTextDocument *m_quickDocument = nullptr; + + signals: + void textDocumentChanged(); + + public: + inline QQuickTextDocument *textDocument() const { return m_quickDocument; }; + void setTextDocument(QQuickTextDocument *textDocument) { + if (!textDocument) return; + m_quickDocument = textDocument; + setDocument(m_quickDocument->textDocument()); + Q_EMIT textDocumentChanged(); + }; +#endif + + public: + enum HighlightingOption { None = 0, - FullyHighlightedBlockQuote = 0x01 + FullyHighlightedBlockQuote = 0x01, + Underline = 0x02 }; Q_DECLARE_FLAGS(HighlightingOptions, HighlightingOption) - MarkdownHighlighter(QTextDocument *parent = nullptr, - HighlightingOptions highlightingOptions = - HighlightingOption::None); + MarkdownHighlighter( + QTextDocument *parent = nullptr, + HighlightingOptions highlightingOptions = HighlightingOption::None); - // we use some predefined numbers here to be compatible with - // the peg-markdown parser + static inline QColor codeBlockBackgroundColor() { + const QBrush brush = _formats[CodeBlock].background(); + + if (!brush.isOpaque()) { + return QColor(Qt::transparent); + } + + return brush.color(); + } + + static constexpr inline bool isOctal(const char c) { + return (c >= '0' && c <= '7'); + } + static constexpr inline bool isHex(const char c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'); + } + static constexpr inline bool isCodeBlock(const int state) { + return state == MarkdownHighlighter::CodeBlock || + state == MarkdownHighlighter::CodeBlockTilde || + state == MarkdownHighlighter::CodeBlockComment || + state == MarkdownHighlighter::CodeBlockTildeComment || + state >= MarkdownHighlighter::CodeCpp; + } + static constexpr inline bool isCodeBlockEnd(const int state) { + return state == MarkdownHighlighter::CodeBlockEnd || + state == MarkdownHighlighter::CodeBlockTildeEnd; + } + static constexpr inline bool isHeading(const int state) { + return state >= H1 && state <= H6; + } + + enum class RangeType { CodeSpan, Emphasis, Link }; + + QPair findPositionInRanges(MarkdownHighlighter::RangeType type, + int blockNum, int pos) const; + bool isPosInACodeSpan(int blockNumber, int position) const; + bool isPosInALink(int blockNumber, int position) const; + QPair getSpanRange(RangeType rangeType, int blockNumber, + int position) const; + + // we used some predefined numbers here to be compatible with + // the peg-Markdown parser enum HighlighterState { NoState = -1, Link = 0, Image = 3, CodeBlock, + CodeBlockComment, Italic = 7, Bold, List, @@ -64,74 +139,222 @@ public: MaskedSyntax, CurrentLineBackgroundColor, BrokenLink, + FrontmatterBlock, + TrailingSpace, + CheckBoxUnChecked, + CheckBoxChecked, + StUnderline, + + // code highlighting + CodeKeyWord = 1000, + CodeString = 1001, + CodeComment = 1002, + CodeType = 1003, + CodeOther = 1004, + CodeNumLiteral = 1005, + CodeBuiltIn = 1006, // internal + CodeBlockIndented = 96, + CodeBlockTildeEnd = 97, + CodeBlockTilde = 98, + CodeBlockTildeComment, CodeBlockEnd = 100, - HeadlineEnd + HeadlineEnd, + FrontmatterBlockEnd, + + // languages + /********* + * When adding a language make sure that its value is a multiple of 2 + * This is because we use the next number as comment for that language + * In case the language doesn't support multiline comments in the + * traditional C++ sense, leave the next value empty. Otherwise mark the + * next value as comment for that language. e.g CodeCpp = 200 + * CodeCppComment = 201 + */ + CodeCpp = 200, + CodeCppComment = 201, + CodeJs = 202, + CodeJsComment = 203, + CodeC = 204, + CodeCComment = 205, + CodeBash = 206, + CodePHP = 208, + CodePHPComment = 209, + CodeQML = 210, + CodeQMLComment = 211, + CodePython = 212, + CodeRust = 214, + CodeRustComment = 215, + CodeJava = 216, + CodeJavaComment = 217, + CodeCSharp = 218, + CodeCSharpComment = 219, + CodeGo = 220, + CodeGoComment = 221, + CodeV = 222, + CodeVComment = 223, + CodeSQL = 224, + CodeSQLComment = 225, + CodeJSON = 226, + CodeXML = 228, + CodeCSS = 230, + CodeCSSComment = 231, + CodeTypeScript = 232, + CodeTypeScriptComment = 233, + CodeYAML = 234, + CodeINI = 236, + CodeTaggerScript = 238, + CodeVex = 240, + CodeVexComment = 241, + CodeCMake = 242, + CodeMake = 244, + CodeNix = 246, + CodeForth = 248, + CodeForthComment = 249, + CodeSystemVerilog = 250, + CodeSystemVerilogComment = 251, + CodeGDScript = 252, + CodeTOML = 254, + CodeTOMLString = 255 }; Q_ENUM(HighlighterState) -// enum BlockState { -// NoBlockState = 0, -// H1, -// H2, -// H3, -// Table, -// CodeBlock, -// CodeBlockEnd -// }; - - void setTextFormats(QHash formats); - void setTextFormat(HighlighterState state, QTextCharFormat format); + static void setTextFormats( + QHash formats); + static void setTextFormat(HighlighterState state, QTextCharFormat format); void clearDirtyBlocks(); - void setHighlightingOptions(HighlightingOptions options); + void setHighlightingOptions(const HighlightingOptions options); void initHighlightingRules(); -signals: + Q_SIGNALS: void highlightingFinished(); -protected slots: + protected Q_SLOTS: void timerTick(); -protected: + protected: struct HighlightingRule { - HighlightingRule(const HighlighterState state_) : state(state_) {} + explicit HighlightingRule(const HighlighterState state_) + : state(state_) {} HighlightingRule() = default; QRegularExpression pattern; + QString shouldContain; HighlighterState state = NoState; - int capturingGroup = 0; - int maskedGroup = 0; - bool useStateAsCurrentBlockState = false; - bool disableIfCurrentStateIsSet = false; + uint8_t capturingGroup = 0; + uint8_t maskedGroup = 0; + }; + struct InlineRange { + int begin; + int end; + RangeType type; + InlineRange() = default; + InlineRange(int begin_, int end_, RangeType type_) + : begin{begin_}, end{end_}, type{type_} {} }; - void highlightBlock(const QString &text) Q_DECL_OVERRIDE; + void highlightBlock(const QString &text) override; - void initTextFormats(int defaultFontSize = 12); + static void initTextFormats(int defaultFontSize = 12); - void highlightMarkdown(QString text); + static void initCodeLangs(); - void highlightHeadline(QString text); + void highlightMarkdown(const QString &text); - void highlightAdditionalRules(QVector &rules, - QString text); + void formatAndMaskRemaining(int formatBegin, int formatLength, + int beginningText, int endText, + const QTextCharFormat &format); - void highlightCodeBlock(QString text); + /****************************** + * BLOCK LEVEL FUNCTIONS + ******************************/ - void highlightCommentBlock(QString text); + void highlightHeadline(const QString &text); - void addDirtyBlock(QTextBlock block); + void highlightSubHeadline(const QString &text, HighlighterState state); + + void highlightAdditionalRules(const QVector &rules, + const QString &text); + + void highlightFrontmatterBlock(const QString &text); + + void highlightCommentBlock(const QString &text); + + void highlightThematicBreak(const QString &text); + + void highlightLists(const QString &text); + + void highlightCheckbox(const QString &text, int curPos); + + /****************************** + * INLINE FUNCTIONS + ******************************/ + + void highlightInlineRules(const QString &text); + + int highlightInlineSpans(const QString &text, int currentPos, + const QChar c); + + void highlightEmAndStrong(const QString &text, const int pos); + + Q_REQUIRED_RESULT int highlightInlineComment(const QString &text, int pos); + + int highlightLinkOrImage(const QString &text, int startIndex); + + void setHeadingStyles(MarkdownHighlighter::HighlighterState rule, + const QRegularExpressionMatch &match, + const int capturedGroup); + + /****************************** + * CODE HIGHLIGHTING FUNCTIONS + ******************************/ + + void highlightIndentedCodeBlock(const QString &text); + + void highlightCodeFence(const QString &text); + + void highlightCodeBlock(const QString &text, + const QString &opener = QStringLiteral("```")); + + void highlightSyntax(const QString &text); + + Q_REQUIRED_RESULT int highlightNumericLiterals(const QString &text, int i); + + Q_REQUIRED_RESULT int highlightStringLiterals(QChar strType, + const QString &text, int i); + + void ymlHighlighter(const QString &text); + + void iniHighlighter(const QString &text); + + void cssHighlighter(const QString &text); + + void xmlHighlighter(const QString &text); + + void makeHighlighter(const QString &text); + + void forthHighlighter(const QString &text); + void taggerScriptHighlighter(const QString &text); + + void gdscriptHighlighter(const QString &text); + void sqlHighlighter(const QString &text); + void tomlHighlighter(const QString &text); + + void addDirtyBlock(const QTextBlock &block); void reHighlightDirtyBlocks(); - QVector _highlightingRulesPre; - QVector _highlightingRulesAfter; - QVector _dirtyTextBlocks; - QHash _formats; - QTimer *_timer; bool _highlightingFinished; HighlightingOptions _highlightingOptions; + QTimer *_timer; + QVector _dirtyTextBlocks; + QVector> _linkRanges; - void setCurrentBlockMargin(HighlighterState state); + QHash> _ranges; + + static QVector _highlightingRules; + static QHash _formats; + static QHash _langStringToEnum; + static constexpr int tildeOffset = 300; }; diff --git a/client/qmarkdowntextedit/media/edit-find-replace.svg b/client/qmarkdowntextedit/media/edit-find-replace.svg index c1c4671..1193301 100644 --- a/client/qmarkdowntextedit/media/edit-find-replace.svg +++ b/client/qmarkdowntextedit/media/edit-find-replace.svg @@ -1,15 +1 @@ - - - - - - + \ No newline at end of file diff --git a/client/qmarkdowntextedit/media/format-text-superscript.svg b/client/qmarkdowntextedit/media/format-text-superscript.svg index 871845e..c9d239c 100644 --- a/client/qmarkdowntextedit/media/format-text-superscript.svg +++ b/client/qmarkdowntextedit/media/format-text-superscript.svg @@ -1,16 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/client/qmarkdowntextedit/media/go-bottom.svg b/client/qmarkdowntextedit/media/go-bottom.svg index 9b85210..42de59c 100644 --- a/client/qmarkdowntextedit/media/go-bottom.svg +++ b/client/qmarkdowntextedit/media/go-bottom.svg @@ -1,156 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/client/qmarkdowntextedit/media/go-top.svg b/client/qmarkdowntextedit/media/go-top.svg index 50b4ca6..98d91cf 100644 --- a/client/qmarkdowntextedit/media/go-top.svg +++ b/client/qmarkdowntextedit/media/go-top.svg @@ -1,476 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/client/qmarkdowntextedit/media/window-close.svg b/client/qmarkdowntextedit/media/window-close.svg index 5d1539d..c7e44ec 100644 --- a/client/qmarkdowntextedit/media/window-close.svg +++ b/client/qmarkdowntextedit/media/window-close.svg @@ -1,148 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - + \ No newline at end of file diff --git a/client/qmarkdowntextedit/old_screenshot.png b/client/qmarkdowntextedit/old_screenshot.png new file mode 100644 index 0000000..f2a1508 Binary files /dev/null and b/client/qmarkdowntextedit/old_screenshot.png differ diff --git a/client/qmarkdowntextedit/qmarkdowntextedit-app.pro b/client/qmarkdowntextedit/qmarkdowntextedit-app.pro new file mode 100644 index 0000000..9d82f8d --- /dev/null +++ b/client/qmarkdowntextedit/qmarkdowntextedit-app.pro @@ -0,0 +1,17 @@ +TARGET = QMarkdownTextedit +TEMPLATE = app +QT += core gui widgets +CONFIG += c++11 + +SOURCES = main.cpp mainwindow.cpp +HEADERS = mainwindow.h +FORMS = mainwindow.ui + +LIBS += -lQMarkdownTextedit -L$$OUT_PWD + +win32: LIBS += -L$$OUT_PWD/release -L$$OUT_PWD/debug + +target.path = $$[QT_INSTALL_BINS] + +INSTALLS += target + diff --git a/client/qmarkdowntextedit/qmarkdowntextedit-headers.pri b/client/qmarkdowntextedit/qmarkdowntextedit-headers.pri index 646e593..68ec123 100644 --- a/client/qmarkdowntextedit/qmarkdowntextedit-headers.pri +++ b/client/qmarkdowntextedit/qmarkdowntextedit-headers.pri @@ -1,6 +1,8 @@ INCLUDEPATH += $$PWD/ HEADERS += \ + $$PWD/linenumberarea.h \ $$PWD/markdownhighlighter.h \ $$PWD/qmarkdowntextedit.h \ + $$PWD/qownlanguagedata.h \ $$PWD/qplaintexteditsearchwidget.h diff --git a/client/qmarkdowntextedit/qmarkdowntextedit-lib.pro b/client/qmarkdowntextedit/qmarkdowntextedit-lib.pro new file mode 100644 index 0000000..b37bcda --- /dev/null +++ b/client/qmarkdowntextedit/qmarkdowntextedit-lib.pro @@ -0,0 +1,34 @@ +TARGET = QMarkdownTextedit +TEMPLATE = lib +QT += core gui widgets +CONFIG += c++11 create_prl no_install_prl create_pc + +include(qmarkdowntextedit.pri) + +TRANSLATIONS += trans/qmarkdowntextedit_de.ts \ + trans/qmarkdowntextedit_zh_CN.ts \ + trans/qmarkdowntextedit_es.ts + +isEmpty(PREFIX):PREFIX=$$[QT_INSTALL_PREFIX] +isEmpty(LIBDIR):LIBDIR=$$[QT_INSTALL_LIBS] +isEmpty(HEADERDIR):HEADERDIR=$${PREFIX}/include/$$TARGET/ +isEmpty(DSRDIR):DSRDIR=$${PREFIX}/share/$$TARGET + +target.path = $${LIBDIR} + +headers.files = $$HEADERS +headers.path = $${HEADERDIR} + +license.files = LICENSE +license.path = $${DSRDIR}/licenses/ + +trans.files = trans/*.qm +trans.path = $${DSRDIR}/translations/ + +QMAKE_PKGCONFIG_NAME = QMarkdownTextedit +QMAKE_PKGCONFIG_DESCRIPTION = C++ Qt QPlainTextEdit widget with markdown highlighting and some other goodies +QMAKE_PKGCONFIG_INCDIR = $${headers.path} +QMAKE_PKGCONFIG_LIBDIR = $${LIBDIR} +QMAKE_PKGCONFIG_DESTDIR = pkgconfig + +INSTALLS += target license headers trans diff --git a/client/qmarkdowntextedit/qmarkdowntextedit-sources.pri b/client/qmarkdowntextedit/qmarkdowntextedit-sources.pri index 352e0bf..43d5fac 100644 --- a/client/qmarkdowntextedit/qmarkdowntextedit-sources.pri +++ b/client/qmarkdowntextedit/qmarkdowntextedit-sources.pri @@ -6,6 +6,7 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets SOURCES += \ $$PWD/markdownhighlighter.cpp \ $$PWD/qmarkdowntextedit.cpp \ + $$PWD/qownlanguagedata.cpp \ $$PWD/qplaintexteditsearchwidget.cpp RESOURCES += \ diff --git a/client/qmarkdowntextedit/qmarkdowntextedit.cpp b/client/qmarkdowntextedit/qmarkdowntextedit.cpp index a6e786d..72ea36b 100644 --- a/client/qmarkdowntextedit/qmarkdowntextedit.cpp +++ b/client/qmarkdowntextedit/qmarkdowntextedit.cpp @@ -1,68 +1,88 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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 "qmarkdowntextedit.h" -#include -#include + +#include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include +#include "linenumberarea.h" +#include "markdownhighlighter.h" + +static const QByteArray _openingCharacters = QByteArrayLiteral("([{<*\"'_~"); +static const QByteArray _closingCharacters = QByteArrayLiteral(")]}>*\"'_~"); QMarkdownTextEdit::QMarkdownTextEdit(QWidget *parent, bool initHighlighter) - : QPlainTextEdit(parent) { + : QPlainTextEdit(parent) { installEventFilter(this); viewport()->installEventFilter(this); - _autoTextOptions = AutoTextOption::None; - _openingCharacters = QStringList() << "(" << "[" << "{" << "<" << "*" - << "\"" << "'" << "_" << "~"; - _closingCharacters = QStringList() << ")" << "]" << "}" << ">" << "*" - << "\"" << "'" << "_" << "~"; + _autoTextOptions = AutoTextOption::BracketClosing; - // markdown highlighting is enabled by default - _highlightingEnabled = true; + _lineNumArea = new LineNumArea(this); + updateLineNumberAreaWidth(0); + + // Markdown highlighting is enabled by default + _highlightingEnabled = initHighlighter; if (initHighlighter) { _highlighter = new MarkdownHighlighter(document()); } -// setHighlightingEnabled(true); QFont font = this->font(); // set the tab stop to the width of 4 spaces in the editor - const int tabStop = 4; + constexpr int tabStop = 4; QFontMetrics metrics(font); + +#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) setTabStopWidth(tabStop * metrics.width(' ')); +#else + setTabStopDistance(tabStop * metrics.horizontalAdvance(QLatin1Char(' '))); +#endif // add shortcuts for duplicating text -// new QShortcut( QKeySequence( "Ctrl+D" ), this, SLOT( duplicateText() ) ); -// new QShortcut( QKeySequence( "Ctrl+Alt+Down" ), this, SLOT( duplicateText() ) ); + // new QShortcut( QKeySequence( "Ctrl+D" ), this, SLOT( duplicateText() ) + // ); new QShortcut( QKeySequence( "Ctrl+Alt+Down" ), this, SLOT( + // duplicateText() ) ); // add a layout to the widget - QVBoxLayout *layout = new QVBoxLayout; + auto *layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); - layout->setMargin(0); layout->addStretch(); this->setLayout(layout); @@ -70,56 +90,112 @@ QMarkdownTextEdit::QMarkdownTextEdit(QWidget *parent, bool initHighlighter) _searchWidget = new QPlainTextEditSearchWidget(this); this->layout()->addWidget(_searchWidget); - QObject::connect(this, SIGNAL(textChanged()), - this, SLOT(adjustRightMargin())); + connect(this, &QPlainTextEdit::textChanged, this, + &QMarkdownTextEdit::adjustRightMargin); + connect(this, &QPlainTextEdit::cursorPositionChanged, this, + &QMarkdownTextEdit::centerTheCursor); + connect(verticalScrollBar(), &QScrollBar::valueChanged, this, + [this](int) { _lineNumArea->update(); }); + connect(this, &QPlainTextEdit::cursorPositionChanged, this, [this]() { + _lineNumArea->update(); + + auto oldArea = blockBoundingGeometry(_textCursor.block()) + .translated(contentOffset()); + _textCursor = textCursor(); + auto newArea = blockBoundingGeometry(_textCursor.block()) + .translated(contentOffset()); + auto areaToUpdate = oldArea | newArea; + viewport()->update(areaToUpdate.toRect()); + }); + connect(document(), &QTextDocument::blockCountChanged, this, + &QMarkdownTextEdit::updateLineNumberAreaWidth); + connect(this, &QPlainTextEdit::updateRequest, this, + &QMarkdownTextEdit::updateLineNumberArea); + + updateSettings(); // workaround for disabled signals up initialization - QTimer::singleShot(300, this, SLOT(adjustRightMargin())); + QTimer::singleShot(300, this, &QMarkdownTextEdit::adjustRightMargin); +} + +void QMarkdownTextEdit::setLineNumbersCurrentLineColor(QColor color) { + _lineNumArea->setCurrentLineColor(std::move(color)); +} + +void QMarkdownTextEdit::setLineNumbersOtherLineColor(QColor color) { + _lineNumArea->setOtherLineColor(std::move(color)); +} + +void QMarkdownTextEdit::setSearchWidgetDebounceDelay(uint debounceDelay) { + _debounceDelay = debounceDelay; + searchWidget()->setDebounceDelay(_debounceDelay); +} + +void QMarkdownTextEdit::setHighlightCurrentLine(bool set) { + _highlightCurrentLine = set; +} + +bool QMarkdownTextEdit::highlightCurrentLine() { return _highlightCurrentLine; } + +void QMarkdownTextEdit::setCurrentLineHighlightColor(const QColor &color) { + _currentLineHighlightColor = color; +} + +QColor QMarkdownTextEdit::currentLineHighlightColor() { + return _currentLineHighlightColor; } /** - * Enables or disables the markdown highlighting + * Enables or disables the Markdown highlighting * * @param enabled */ void QMarkdownTextEdit::setHighlightingEnabled(bool enabled) { - if (_highlightingEnabled == enabled) { + if (_highlightingEnabled == enabled || _highlighter == nullptr) { return; } - _highlighter->setDocument(enabled ? document() : Q_NULLPTR); _highlightingEnabled = enabled; + _highlighter->setDocument(enabled ? document() : Q_NULLPTR); if (enabled) { _highlighter->rehighlight(); } } +/** + * @brief Returns if highlighting is enabled + * @return Returns true if highlighting is enabled, otherwise false + */ +bool QMarkdownTextEdit::highlightingEnabled() const { + return _highlightingEnabled && _highlighter != nullptr; +} + /** * Leave a little space on the right side if the document is too long, so * that the search buttons don't get visually blocked by the scroll bar */ void QMarkdownTextEdit::adjustRightMargin() { QMargins margins = layout()->contentsMargins(); - int rightMargin = document()->size().height() > - viewport()->size().height() ? 24 : 0; + const int rightMargin = + document()->size().height() > viewport()->size().height() ? 24 : 0; margins.setRight(rightMargin); layout()->setContentsMargins(margins); } bool QMarkdownTextEdit::eventFilter(QObject *obj, QEvent *event) { - //qDebug() << event->type(); + // qDebug() << event->type(); if (event->type() == QEvent::HoverMove) { - QMouseEvent *mouseEvent = static_cast(event); + auto *mouseEvent = static_cast(event); QWidget *viewPort = this->viewport(); // toggle cursor when control key has been pressed or released - viewPort->setCursor(mouseEvent->modifiers().testFlag( - Qt::ControlModifier) ? - Qt::PointingHandCursor : - Qt::IBeamCursor); + viewPort->setCursor( + mouseEvent->modifiers().testFlag(Qt::ControlModifier) + ? Qt::PointingHandCursor + : Qt::IBeamCursor); } else if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); + auto *keyEvent = static_cast(event); // set cursor to pointing hand if control key was pressed if (keyEvent->modifiers().testFlag(Qt::ControlModifier)) { @@ -135,92 +211,114 @@ bool QMarkdownTextEdit::eventFilter(QObject *obj, QEvent *event) { if ((keyEvent->key() == Qt::Key_Escape) && _searchWidget->isVisible()) { _searchWidget->deactivate(); return true; + } else if (keyEvent->key() == Qt::Key_Insert && + keyEvent->modifiers().testFlag(Qt::NoModifier)) { + setOverwriteMode(!overwriteMode()); + + // This solves a UI glitch if the visual cursor was not properly + // updated when characters have different widths + QTextCursor cursor = this->textCursor(); + cursor.movePosition(QTextCursor::Right); + setTextCursor(cursor); + cursor.movePosition(QTextCursor::Left); + setTextCursor(cursor); + + return false; } else if ((keyEvent->key() == Qt::Key_Tab) || - (keyEvent->key() == Qt::Key_Backtab)) { + (keyEvent->key() == Qt::Key_Backtab)) { // handle entered tab and reverse tab keys - return handleTabEntered( - keyEvent->key() == Qt::Key_Backtab); + return handleTabEntered(keyEvent->key() == Qt::Key_Backtab); } else if ((keyEvent->key() == Qt::Key_F) && - keyEvent->modifiers().testFlag(Qt::ControlModifier)) { + keyEvent->modifiers().testFlag(Qt::ControlModifier)) { _searchWidget->activate(); return true; } else if ((keyEvent->key() == Qt::Key_R) && - keyEvent->modifiers().testFlag(Qt::ControlModifier)) { + keyEvent->modifiers().testFlag(Qt::ControlModifier)) { _searchWidget->activateReplace(); return true; -// } else if (keyEvent->key() == Qt::Key_Delete) { + // } else if (keyEvent->key() == Qt::Key_Delete) { } else if (keyEvent->key() == Qt::Key_Backspace) { - return handleBracketRemoval(); + return handleBackspaceEntered(); } else if (keyEvent->key() == Qt::Key_Asterisk) { - return handleBracketClosing("*"); + return handleBracketClosing(QLatin1Char('*')); } else if (keyEvent->key() == Qt::Key_QuoteDbl) { - return quotationMarkCheck("\""); + return quotationMarkCheck(QLatin1Char('"')); // apostrophe bracket closing is temporary disabled because // apostrophes are used in different contexts -// } else if (keyEvent->key() == Qt::Key_Apostrophe) { -// return handleBracketClosing("'"); + // } else if (keyEvent->key() == Qt::Key_Apostrophe) { + // return handleBracketClosing("'"); // underline bracket closing is temporary disabled because // underlines are used in different contexts -// } else if (keyEvent->key() == Qt::Key_Underscore) { -// return handleBracketClosing("_"); - } - else if (keyEvent->key() == Qt::Key_QuoteLeft) { - return quotationMarkCheck("`"); + // } else if (keyEvent->key() == Qt::Key_Underscore) { + // return handleBracketClosing("_"); + } else if (keyEvent->key() == Qt::Key_QuoteLeft) { + return quotationMarkCheck(QLatin1Char('`')); } else if (keyEvent->key() == Qt::Key_AsciiTilde) { - return handleBracketClosing("~"); + return handleBracketClosing(QLatin1Char('~')); #ifdef Q_OS_MAC } else if (keyEvent->modifiers().testFlag(Qt::AltModifier) && - keyEvent->key() == Qt::Key_ParenLeft) { + keyEvent->key() == Qt::Key_ParenLeft) { // bracket closing for US keyboard on macOS - return handleBracketClosing("{", "}"); + return handleBracketClosing(QLatin1Char('{'), QLatin1Char('}')); #endif } else if (keyEvent->key() == Qt::Key_ParenLeft) { - return handleBracketClosing("(", ")"); + return handleBracketClosing(QLatin1Char('('), QLatin1Char(')')); } else if (keyEvent->key() == Qt::Key_BraceLeft) { - return handleBracketClosing("{", "}"); + return handleBracketClosing(QLatin1Char('{'), QLatin1Char('}')); } else if (keyEvent->key() == Qt::Key_BracketLeft) { - return handleBracketClosing("[", "]"); + return handleBracketClosing(QLatin1Char('['), QLatin1Char(']')); } else if (keyEvent->key() == Qt::Key_Less) { - return handleBracketClosing("<", ">"); + return handleBracketClosing(QLatin1Char('<'), QLatin1Char('>')); #ifdef Q_OS_MAC } else if (keyEvent->modifiers().testFlag(Qt::AltModifier) && keyEvent->key() == Qt::Key_ParenRight) { // bracket closing for US keyboard on macOS - return bracketClosingCheck("{", "}"); + return bracketClosingCheck(QLatin1Char('{'), QLatin1Char('}')); #endif } else if (keyEvent->key() == Qt::Key_ParenRight) { - return bracketClosingCheck("(", ")"); + return bracketClosingCheck(QLatin1Char('('), QLatin1Char(')')); } else if (keyEvent->key() == Qt::Key_BraceRight) { - return bracketClosingCheck("{", "}"); + return bracketClosingCheck(QLatin1Char('{'), QLatin1Char('}')); } else if (keyEvent->key() == Qt::Key_BracketRight) { - return bracketClosingCheck("[", "]"); - } else if (keyEvent->key() == Qt::Key_Return && - keyEvent->modifiers().testFlag(Qt::ShiftModifier)) { + return bracketClosingCheck(QLatin1Char('['), QLatin1Char(']')); + } else if (keyEvent->key() == Qt::Key_Greater) { + return bracketClosingCheck(QLatin1Char('<'), QLatin1Char('>')); + } else if ((keyEvent->key() == Qt::Key_Return || + keyEvent->key() == Qt::Key_Enter) && + !isReadOnly() && + keyEvent->modifiers().testFlag(Qt::ShiftModifier)) { QTextCursor cursor = this->textCursor(); cursor.insertText(" \n"); return true; - } else if (keyEvent->key() == Qt::Key_Return && + } else if ((keyEvent->key() == Qt::Key_Return || + keyEvent->key() == Qt::Key_Enter) && + !isReadOnly() && keyEvent->modifiers().testFlag(Qt::ControlModifier)) { QTextCursor cursor = this->textCursor(); - cursor.movePosition(QTextCursor::EndOfLine); - cursor.insertText("\n"); + cursor.movePosition(QTextCursor::EndOfBlock); + cursor.insertText(QStringLiteral("\n")); setTextCursor(cursor); return true; - } else if (keyEvent == QKeySequence::Copy || keyEvent == QKeySequence::Cut) { + } else if (keyEvent == QKeySequence::Copy || + keyEvent == QKeySequence::Cut) { QTextCursor cursor = this->textCursor(); if (!cursor.hasSelection()) { QString text; - if (cursor.block().length() <= 1) // no content + if (cursor.block().length() <= 1) // no content text = "\n"; else { - //cursor.select(QTextCursor::BlockUnderCursor); // negative, it will include the previous paragraph separator + // cursor.select(QTextCursor::BlockUnderCursor); // + // negative, it will include the previous paragraph + // separator cursor.movePosition(QTextCursor::StartOfBlock); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfBlock, + QTextCursor::KeepAnchor); text = cursor.selectedText(); if (!cursor.atEnd()) { text += "\n"; // this is the paragraph separator - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 1); + cursor.movePosition(QTextCursor::NextCharacter, + QTextCursor::KeepAnchor, 1); } } if (keyEvent == QKeySequence::Cut) { @@ -228,52 +326,49 @@ bool QMarkdownTextEdit::eventFilter(QObject *obj, QEvent *event) { cursor.deletePreviousChar(); else cursor.removeSelectedText(); - cursor.movePosition(QTextCursor::StartOfLine); + cursor.movePosition(QTextCursor::StartOfBlock); setTextCursor(cursor); } qApp->clipboard()->setText(text); return true; } - } - else if (keyEvent == QKeySequence::Paste) { - if (qApp->clipboard()->ownsClipboard() && - QRegExp("[^\n]*\n$").exactMatch(qApp->clipboard()->text())) { - QTextCursor cursor = this->textCursor(); - if (!cursor.hasSelection()) { - cursor.movePosition(QTextCursor::StartOfLine); - setTextCursor(cursor); - } - } } else if ((keyEvent->key() == Qt::Key_Down) && - keyEvent->modifiers().testFlag(Qt::ControlModifier) && - keyEvent->modifiers().testFlag(Qt::AltModifier)) { + keyEvent->modifiers().testFlag(Qt::ControlModifier) && + keyEvent->modifiers().testFlag(Qt::AltModifier)) { // duplicate text with `Ctrl + Alt + Down` duplicateText(); return true; #ifndef Q_OS_MAC } else if ((keyEvent->key() == Qt::Key_Down) && - keyEvent->modifiers().testFlag(Qt::ControlModifier)) { + keyEvent->modifiers().testFlag(Qt::ControlModifier) && + !keyEvent->modifiers().testFlag(Qt::ShiftModifier)) { // scroll the page down auto *scrollBar = verticalScrollBar(); scrollBar->setSliderPosition(scrollBar->sliderPosition() + 1); return true; } else if ((keyEvent->key() == Qt::Key_Up) && - keyEvent->modifiers().testFlag(Qt::ControlModifier)) { + keyEvent->modifiers().testFlag(Qt::ControlModifier) && + !keyEvent->modifiers().testFlag(Qt::ShiftModifier)) { // scroll the page up auto *scrollBar = verticalScrollBar(); scrollBar->setSliderPosition(scrollBar->sliderPosition() - 1); return true; #endif } else if ((keyEvent->key() == Qt::Key_Down) && - keyEvent->modifiers().testFlag(Qt::NoModifier)) { + keyEvent->modifiers().testFlag(Qt::NoModifier)) { // if you are in the last line and press cursor down the cursor will // jump to the end of the line QTextCursor cursor = textCursor(); if (cursor.position() >= document()->lastBlock().position()) { cursor.movePosition(QTextCursor::EndOfLine); - setTextCursor(cursor); + + // check if we are really in the last line, not only in + // the last block + if (cursor.atBlockEnd()) { + setTextCursor(cursor); + } } - return false; + return QPlainTextEdit::eventFilter(obj, event); } else if ((keyEvent->key() == Qt::Key_Up) && keyEvent->modifiers().testFlag(Qt::NoModifier)) { // if you are in the first line and press cursor up the cursor will @@ -284,29 +379,79 @@ bool QMarkdownTextEdit::eventFilter(QObject *obj, QEvent *event) { if (cursor.position() <= endOfFirstLinePos) { cursor.movePosition(QTextCursor::StartOfLine); - setTextCursor(cursor); + + // check if we are really in the first line, not only in + // the first block + if (cursor.atBlockStart()) { + setTextCursor(cursor); + } } - return false; - } else if (keyEvent->key() == Qt::Key_Return) { + return QPlainTextEdit::eventFilter(obj, event); + } else if (keyEvent->key() == Qt::Key_Return || + keyEvent->key() == Qt::Key_Enter) { return handleReturnEntered(); } else if ((keyEvent->key() == Qt::Key_F3)) { _searchWidget->doSearch( - !keyEvent->modifiers().testFlag(Qt::ShiftModifier)); + !keyEvent->modifiers().testFlag(Qt::ShiftModifier)); return true; + } else if ((keyEvent->key() == Qt::Key_Z) && + (keyEvent->modifiers().testFlag(Qt::ControlModifier)) && + !(keyEvent->modifiers().testFlag(Qt::ShiftModifier))) { + undo(); + return true; + } else if ((keyEvent->key() == Qt::Key_Down) && + (keyEvent->modifiers().testFlag(Qt::ControlModifier)) && + (keyEvent->modifiers().testFlag(Qt::ShiftModifier))) { + moveTextUpDown(false); + return true; + } else if ((keyEvent->key() == Qt::Key_Up) && + (keyEvent->modifiers().testFlag(Qt::ControlModifier)) && + (keyEvent->modifiers().testFlag(Qt::ShiftModifier))) { + moveTextUpDown(true); + return true; +#ifdef Q_OS_MAC + // https://github.com/pbek/QOwnNotes/issues/1593 + // https://github.com/pbek/QOwnNotes/issues/2643 + } else if (keyEvent->key() == Qt::Key_Home) { + QTextCursor cursor = textCursor(); + // Meta is Control on macOS + cursor.movePosition( + keyEvent->modifiers().testFlag(Qt::MetaModifier) + ? QTextCursor::Start + : QTextCursor::StartOfLine, + keyEvent->modifiers().testFlag(Qt::ShiftModifier) + ? QTextCursor::KeepAnchor + : QTextCursor::MoveAnchor); + this->setTextCursor(cursor); + return true; + } else if (keyEvent->key() == Qt::Key_End) { + QTextCursor cursor = textCursor(); + // Meta is Control on macOS + cursor.movePosition( + keyEvent->modifiers().testFlag(Qt::MetaModifier) + ? QTextCursor::End + : QTextCursor::EndOfLine, + keyEvent->modifiers().testFlag(Qt::ShiftModifier) + ? QTextCursor::KeepAnchor + : QTextCursor::MoveAnchor); + this->setTextCursor(cursor); + return true; +#endif } - return false; + return QPlainTextEdit::eventFilter(obj, event); } else if (event->type() == QEvent::KeyRelease) { - QKeyEvent *keyEvent = static_cast(event); + auto *keyEvent = static_cast(event); // reset cursor if control key was released if (keyEvent->key() == Qt::Key_Control) { resetMouseCursor(); } - return false; + return QPlainTextEdit::eventFilter(obj, event); } else if (event->type() == QEvent::MouseButtonRelease) { - QMouseEvent *mouseEvent = static_cast(event); + _mouseButtonDown = false; + auto *mouseEvent = static_cast(event); // track `Ctrl + Click` in the text edit if ((obj == this->viewport()) && @@ -315,6 +460,23 @@ bool QMarkdownTextEdit::eventFilter(QObject *obj, QEvent *event) { // open the link (if any) at the current position // in the noteTextEdit openLinkAtCursorPosition(); + return true; + } + } else if (event->type() == QEvent::MouseButtonPress) { + _mouseButtonDown = true; + } else if (event->type() == QEvent::MouseButtonDblClick) { + _mouseButtonDown = true; + } else if (event->type() == QEvent::Wheel) { + auto *wheel = dynamic_cast(event); + + // emit zoom signals + if (wheel->modifiers() == Qt::ControlModifier) { + if (wheel->angleDelta().y() > 0) { + Q_EMIT zoomIn(); + } else { + Q_EMIT zoomOut(); + } + return true; } } @@ -322,6 +484,186 @@ bool QMarkdownTextEdit::eventFilter(QObject *obj, QEvent *event) { return QPlainTextEdit::eventFilter(obj, event); } +void QMarkdownTextEdit::centerTheCursor() { + if (_mouseButtonDown || !_centerCursor) { + return; + } + + // Centers the cursor every time, but not on the top and bottom, + // bottom is done by setCenterOnScroll() in updateSettings() + centerCursor(); + + /* + QRect cursor = cursorRect(); + QRect vp = viewport()->rect(); + + qDebug() << __func__ << " - 'cursor.top': " << cursor.top(); + qDebug() << __func__ << " - 'cursor.bottom': " << cursor.bottom(); + qDebug() << __func__ << " - 'vp': " << vp.bottom(); + + int bottom = 0; + int top = 0; + + qDebug() << __func__ << " - 'viewportMargins().top()': " + << viewportMargins().top(); + + qDebug() << __func__ << " - 'viewportMargins().bottom()': " + << viewportMargins().bottom(); + + int vpBottom = viewportMargins().top() + viewportMargins().bottom() + + vp.bottom(); int vpCenter = vpBottom / 2; int cBottom = cursor.bottom() + + viewportMargins().top(); + + qDebug() << __func__ << " - 'vpBottom': " << vpBottom; + qDebug() << __func__ << " - 'vpCenter': " << vpCenter; + qDebug() << __func__ << " - 'cBottom': " << cBottom; + + + if (cBottom >= vpCenter) { + bottom = cBottom + viewportMargins().top() / 2 + + viewportMargins().bottom() / 2 - (vp.bottom() / 2); + // bottom = cBottom - (vp.bottom() / 2); + // bottom *= 1.5; + } + + // setStyleSheet(QString("QPlainTextEdit {padding-bottom: + %1px;}").arg(QString::number(bottom))); + + // if (cursor.top() < (vp.bottom() / 2)) { + // top = (vp.bottom() / 2) - cursor.top() + viewportMargins().top() / + 2 + viewportMargins().bottom() / 2; + //// top *= -1; + //// bottom *= 1.5; + // } + qDebug() << __func__ << " - 'top': " << top; + qDebug() << __func__ << " - 'bottom': " << bottom; + setViewportMargins(0,top,0, bottom); + + + // QScrollBar* scrollbar = verticalScrollBar(); + // + // qDebug() << __func__ << " - 'scrollbar->value();': " << + scrollbar->value();; + // qDebug() << __func__ << " - 'scrollbar->maximum();': " + // << scrollbar->maximum();; + + + // scrollbar->setValue(scrollbar->value() - offset.y()); + // + // setViewportMargins + + // setViewportMargins(0, 0, 0, bottom); + */ +} + +/* + * Handle the undo event ourselves + * Retains the selected text as selected after undo if + * bracket closing was used otherwise performs normal undo + */ +void QMarkdownTextEdit::undo() { + if (isReadOnly()) { + return; + } + + QTextCursor cursor = textCursor(); + // if no text selected, call undo + if (!cursor.hasSelection()) { + QPlainTextEdit::undo(); + return; + } + + // if text is selected and bracket closing was used + // we retain our selection + if (_handleBracketClosingUsed) { + // get the selection + int selectionEnd = cursor.selectionEnd(); + int selectionStart = cursor.selectionStart(); + // call undo + QPlainTextEdit::undo(); + // select again + cursor.setPosition(selectionStart - 1); + cursor.setPosition(selectionEnd - 1, QTextCursor::KeepAnchor); + this->setTextCursor(cursor); + _handleBracketClosingUsed = false; + } else { + // if text was selected but bracket closing wasn't used + // do normal undo + QPlainTextEdit::undo(); + return; + } +} + +void QMarkdownTextEdit::moveTextUpDown(bool up) { + if (isReadOnly()) { + return; + } + + QTextCursor cursor = textCursor(); + QTextCursor move = cursor; + + move.setVisualNavigation(false); + + move.beginEditBlock(); // open an edit block to keep undo operations sane + bool hasSelection = cursor.hasSelection(); + + if (hasSelection) { + // if there's a selection inside the block, we select the whole block + move.setPosition(cursor.selectionStart()); + move.movePosition(QTextCursor::StartOfBlock); + move.setPosition(cursor.selectionEnd(), QTextCursor::KeepAnchor); + move.movePosition( + move.atBlockStart() ? QTextCursor::Left : QTextCursor::EndOfBlock, + QTextCursor::KeepAnchor); + } else { + move.movePosition(QTextCursor::StartOfBlock); + move.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + } + + // get the text of the current block + QString text = move.selectedText(); + + move.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); + move.removeSelectedText(); + + if (up) { // up key + move.movePosition(QTextCursor::PreviousBlock); + move.insertBlock(); + move.movePosition(QTextCursor::Left); + } else { // down key + move.movePosition(QTextCursor::EndOfBlock); + if (move.atBlockStart()) { // empty block + move.movePosition(QTextCursor::NextBlock); + move.insertBlock(); + move.movePosition(QTextCursor::Left); + } else { + move.insertBlock(); + } + } + + int start = move.position(); + move.clearSelection(); + move.insertText(text); + int end = move.position(); + + // reselect + if (hasSelection) { + move.setPosition(end); + move.setPosition(start, QTextCursor::KeepAnchor); + } else { + move.setPosition(start); + } + + move.endEditBlock(); + + setTextCursor(move); +} + +void QMarkdownTextEdit::setLineNumberEnabled(bool enabled) { + _lineNumArea->setLineNumAreaEnabled(enabled); + updateLineNumberAreaWidth(0); +} + /** * Resets the cursor to Qt::IBeamCursor */ @@ -345,98 +687,116 @@ void QMarkdownTextEdit::focusOutEvent(QFocusEvent *event) { * @param closingCharacter * @return */ -bool QMarkdownTextEdit::handleBracketClosing(QString openingCharacter, - QString closingCharacter) { - // check if bracket closing is enabled - if (!(_autoTextOptions & AutoTextOption::BracketClosing)) { +bool QMarkdownTextEdit::handleBracketClosing(const QChar openingCharacter, + QChar closingCharacter) { + // check if bracket closing or read-only are enabled + if (!(_autoTextOptions & AutoTextOption::BracketClosing) || isReadOnly()) { return false; } QTextCursor cursor = textCursor(); - // get the current text from the block (inserted character not included) - QString text = cursor.block().text(); - - if (closingCharacter.isEmpty()) { + if (closingCharacter.isNull()) { closingCharacter = openingCharacter; } - QString selectedText = cursor.selectedText(); + const QString selectedText = cursor.selectedText(); // When user currently has text selected, we prepend the openingCharacter // and append the closingCharacter. E.g. 'text' -> '(text)'. We keep the // current selectedText selected. - // - // TODO(sanderboom): how to make ctrl-z keep the selectedText selected? - if (selectedText != "") { + if (!selectedText.isEmpty()) { // Insert. The selectedText is overwritten. - cursor.insertText(openingCharacter); - cursor.insertText(selectedText); - cursor.insertText(closingCharacter); + const QString newText = + openingCharacter + selectedText + closingCharacter; + cursor.insertText(newText); // Re-select the selectedText. - int selectionEnd = cursor.position() - 1; - int selectionStart = selectionEnd - selectedText.length(); + const int selectionEnd = cursor.position() - 1; + const int selectionStart = selectionEnd - selectedText.length(); + cursor.setPosition(selectionStart); cursor.setPosition(selectionEnd, QTextCursor::KeepAnchor); this->setTextCursor(cursor); - + _handleBracketClosingUsed = true; return true; - } else { - // if not text was selected check if we are inside the text - int positionInBlock = cursor.position() - cursor.block().position(); - - // only allow the closing if the cursor was at the end of a block - // we are making a special allowance for openingCharacter == * - if ((positionInBlock != text.count()) && - !((openingCharacter == "*") && - (positionInBlock == (text.count() - 1)))) { - return false; - } } - + // get the current text from the block (inserted character not included) // Remove whitespace at start of string (e.g. in multilevel-lists). - text = text.remove(QRegExp("^\\s+")); + static QRegularExpression regex1("^\\s+"); + const QString text = cursor.block().text().remove(regex1); + + const int pib = cursor.positionInBlock(); + bool isPreviousAsterisk = + pib > 0 && pib < text.length() && text.at(pib - 1) == '*'; + bool isNextAsterisk = pib < text.length() && text.at(pib) == '*'; + bool isMaybeBold = isPreviousAsterisk && isNextAsterisk; + if (pib < text.length() && !isMaybeBold && !text.at(pib).isSpace()) { + return false; + } // Default positions to move the cursor back. int cursorSubtract = 1; - // Special handling for `*` opening character, as this could be: // - start of a list (or sublist); // - start of a bold text; - if (openingCharacter == "*") { - // User wants: '*'. + if (openingCharacter == QLatin1Char('*')) { + // don't auto complete in code block + bool isInCode = + MarkdownHighlighter::isCodeBlock(cursor.block().userState()); + // we only do auto completion if there is a space before the cursor pos + bool hasSpaceOrAsteriskBefore = !text.isEmpty() && pib > 0 && + (text.at(pib - 1).isSpace() || + text.at(pib - 1) == QLatin1Char('*')); // This could be the start of a list, don't autocomplete. - if (text == "") { + bool isEmpty = text.isEmpty(); + + if (isInCode || !hasSpaceOrAsteriskBefore || isEmpty) { return false; } + + // bold + if (isPreviousAsterisk && isNextAsterisk) { + cursorSubtract = 1; + } + // User wants: '**'. // Not the start of a list, probably bold text. We autocomplete with // extra closingCharacter and cursorSubtract to 'catchup'. - else if (text == "*") { - closingCharacter = "**"; + if (text == QLatin1String("*")) { + cursor.insertText(QStringLiteral("*")); cursorSubtract = 2; } - // User wants: '* *'. - // We are in a list already, proceed as normal (autocomplete). - else if (text == "* ") { - // no-op. - } } - // Auto completion for ``` pair - if (openingCharacter == "`") { - if (QRegExp("[^`]*``").exactMatch(text)) { - cursor.insertText(openingCharacter); - cursor.insertText(openingCharacter); + // Auto-completion for ``` pair + if (openingCharacter == QLatin1Char('`')) { +#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) + if (QRegExp(QStringLiteral("[^`]*``")).exactMatch(text)) { +#else + if (QRegularExpression( + QRegularExpression::anchoredPattern(QStringLiteral("[^`]*``"))) + .match(text) + .hasMatch()) { +#endif + cursor.insertText(QStringLiteral("``")); cursorSubtract = 3; } } + // don't auto complete in code block + if (openingCharacter == QLatin1Char('<') && + MarkdownHighlighter::isCodeBlock(cursor.block().userState())) { + return false; + } + + cursor.beginEditBlock(); cursor.insertText(openingCharacter); cursor.insertText(closingCharacter); cursor.setPosition(cursor.position() - cursorSubtract); + cursor.endEditBlock(); + setTextCursor(cursor); return true; } @@ -448,47 +808,46 @@ bool QMarkdownTextEdit::handleBracketClosing(QString openingCharacter, * @param closingCharacter * @return */ -bool QMarkdownTextEdit::bracketClosingCheck(QString openingCharacter, - QString closingCharacter) { - // check if bracket closing is enabled - if (!(_autoTextOptions & AutoTextOption::BracketClosing)) { +bool QMarkdownTextEdit::bracketClosingCheck(const QChar openingCharacter, + QChar closingCharacter) { + // check if bracket closing or read-only are enabled + if (!(_autoTextOptions & AutoTextOption::BracketClosing) || isReadOnly()) { return false; } - if (closingCharacter.isEmpty()) { + if (closingCharacter.isNull()) { closingCharacter = openingCharacter; } QTextCursor cursor = textCursor(); - int positionInBlock = cursor.position() - cursor.block().position(); + const int positionInBlock = cursor.positionInBlock(); // get the current text from the block - QString text = cursor.block().text(); - int textLength = text.length(); + const QString text = cursor.block().text(); + const int textLength = text.length(); // if we are at the end of the line we just want to enter the character if (positionInBlock >= textLength) { return false; } - QString currentChar = text.at(positionInBlock); + const QChar currentChar = text.at(positionInBlock); - if (closingCharacter == openingCharacter) { + // if (closingCharacter == openingCharacter) { - } + // } qDebug() << __func__ << " - 'currentChar': " << currentChar; - // if the current character is not the closing character we just want to // enter the character if (currentChar != closingCharacter) { return false; } - QString leftText = text.left(positionInBlock); - int openingCharacterCount = leftText.count(openingCharacter); - int closingCharacterCount = leftText.count(closingCharacter); + const QString leftText = text.left(positionInBlock); + const int openingCharacterCount = leftText.count(openingCharacter); + const int closingCharacterCount = leftText.count(closingCharacter); // if there were enough opening characters just enter the character if (openingCharacterCount < (closingCharacterCount + 1)) { @@ -508,25 +867,32 @@ bool QMarkdownTextEdit::bracketClosingCheck(QString openingCharacter, * @param quotationCharacter * @return */ -bool QMarkdownTextEdit::quotationMarkCheck(QString quotationCharacter) { - // check if bracket closing is enabled - if (!(_autoTextOptions & AutoTextOption::BracketClosing)) { +bool QMarkdownTextEdit::quotationMarkCheck(const QChar quotationCharacter) { + // check if bracket closing or read-only are enabled + if (!(_autoTextOptions & AutoTextOption::BracketClosing) || isReadOnly()) { return false; } QTextCursor cursor = textCursor(); - int positionInBlock = cursor.position() - cursor.block().position(); + const int positionInBlock = cursor.positionInBlock(); // get the current text from the block - QString text = cursor.block().text(); - int textLength = text.length(); + const QString text = cursor.block().text(); + const int textLength = text.length(); + + // if last char is not space, we are at word end, no autocompletion + const bool isBacktick = quotationCharacter == '`'; + if (!isBacktick && positionInBlock != 0 && + !text.at(positionInBlock - 1).isSpace()) { + return false; + } // if we are at the end of the line we just want to enter the character if (positionInBlock >= textLength) { return handleBracketClosing(quotationCharacter); } - QString currentChar = text.at(positionInBlock); + const QChar currentChar = text.at(positionInBlock); // if the current character is not the quotation character we just want to // enter the character @@ -540,15 +906,31 @@ bool QMarkdownTextEdit::quotationMarkCheck(QString quotationCharacter) { return true; } +/*********************************** + * helper methods for char removal + * Rules for (') and ("): + * if [sp]" -> opener (sp = space) + * if "[sp] -> closer + ***********************************/ +bool isQuotOpener(int position, const QString &text) { + if (position == 0) return true; + const int prevCharPos = position - 1; + return text.at(prevCharPos).isSpace(); +} +bool isQuotCloser(int position, const QString &text) { + const int nextCharPos = position + 1; + if (nextCharPos >= text.length()) return true; + return text.at(nextCharPos).isSpace(); +} + /** - * Handles removing of matching brackets and other markdown characters + * Handles removing of matching brackets and other Markdown characters * Only works with backspace to remove text * * @return */ -bool QMarkdownTextEdit::handleBracketRemoval() { - // check if bracket removal is enabled - if (!(_autoTextOptions & AutoTextOption::BracketRemoval)) { +bool QMarkdownTextEdit::handleBackspaceEntered() { + if (!(_autoTextOptions & AutoTextOption::BracketRemoval) || isReadOnly()) { return false; } @@ -560,7 +942,12 @@ bool QMarkdownTextEdit::handleBracketRemoval() { } int position = cursor.position(); - int positionInBlock = position - cursor.block().position(); + const int positionInBlock = cursor.positionInBlock(); + int block = cursor.block().blockNumber(); + + if (_highlighter) + if (_highlighter->isPosInACodeSpan(block, positionInBlock - 1)) + return false; // return if backspace was pressed at the beginning of a block if (positionInBlock == 0) { @@ -568,32 +955,77 @@ bool QMarkdownTextEdit::handleBracketRemoval() { } // get the current text from the block - QString text = cursor.block().text(); - QString charInFront = text.at(positionInBlock - 1); - int openingCharacterIndex = _openingCharacters.indexOf(charInFront); + const QString text = cursor.block().text(); - // return if the character in front of the cursor is no opening character - if (openingCharacterIndex == -1) { - return false; + char charToRemove{}; + + // current char + const char charInFront = text.at(positionInBlock - 1).toLatin1(); + + if (charInFront == '*') + return handleCharRemoval(MarkdownHighlighter::RangeType::Emphasis, + block, positionInBlock - 1); + else if (charInFront == '`') + return handleCharRemoval(MarkdownHighlighter::RangeType::CodeSpan, + block, positionInBlock - 1); + + // handle removal of ", ', and brackets + + // is it opener? + int pos = _openingCharacters.indexOf(charInFront); + // for " and ' + bool isOpener = false; + bool isCloser = false; + if (pos == 5 || pos == 6) { + isOpener = isQuotOpener(positionInBlock - 1, text); + } else { + isOpener = pos != -1; + } + if (isOpener) { + charToRemove = _closingCharacters.at(pos); + } else { + // is it closer? + pos = _closingCharacters.indexOf(charInFront); + if (pos == 5 || pos == 6) + isCloser = isQuotCloser(positionInBlock - 1, text); + else + isCloser = pos != -1; + if (isCloser) + charToRemove = _openingCharacters.at(pos); + else + return false; } - QString closingCharacter = _closingCharacters.at(openingCharacterIndex); - - // remove everything in front of the cursor - text.remove(0, positionInBlock); - int closingCharacterIndex = text.indexOf(closingCharacter); - - // return if no closing character was found in the text after the cursor - if (closingCharacterIndex == -1) { - return false; + int charToRemoveIndex = -1; + if (isOpener) { + bool closer = true; + charToRemoveIndex = text.indexOf(charToRemove, positionInBlock); + if (charToRemoveIndex == -1) return false; + if (pos == 5 || pos == 6) + closer = isQuotCloser(charToRemoveIndex, text); + if (!closer) return false; + cursor.setPosition(position + (charToRemoveIndex - positionInBlock)); + cursor.deleteChar(); + } else if (isCloser) { + charToRemoveIndex = text.lastIndexOf(charToRemove, positionInBlock - 2); + if (charToRemoveIndex == -1) return false; + bool opener = true; + if (pos == 5 || pos == 6) + opener = isQuotOpener(charToRemoveIndex, text); + if (!opener) return false; + const int pos = position - (positionInBlock - charToRemoveIndex); + cursor.setPosition(pos); + cursor.deleteChar(); + position -= 1; + } else { + charToRemoveIndex = text.lastIndexOf(charToRemove, positionInBlock - 2); + if (charToRemoveIndex == -1) return false; + const int pos = position - (positionInBlock - charToRemoveIndex); + cursor.setPosition(pos); + cursor.deleteChar(); + position -= 1; } - // removing the closing character - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, - closingCharacterIndex); - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - // moving the cursor back to the old position so the previous character // can be removed cursor.setPosition(position); @@ -601,79 +1033,161 @@ bool QMarkdownTextEdit::handleBracketRemoval() { return false; } +bool QMarkdownTextEdit::handleCharRemoval(MarkdownHighlighter::RangeType type, + int block, int position) { + if (!_highlighter) return false; + + auto range = _highlighter->findPositionInRanges(type, block, position); + if (range == QPair{-1, -1}) return false; + + int charToRemovePos = range.first; + if (position == range.first) charToRemovePos = range.second; + + QTextCursor cursor = textCursor(); + auto gpos = cursor.position(); + + if (charToRemovePos > position) { + cursor.setPosition(gpos + (charToRemovePos - (position + 1))); + } else { + cursor.setPosition(gpos - (position - charToRemovePos + 1)); + gpos--; + } + + cursor.deleteChar(); + cursor.setPosition(gpos); + setTextCursor(cursor); + return false; +} + +void QMarkdownTextEdit::updateLineNumAreaGeometry() { + const auto contentsRect = this->contentsRect(); + const QRect newGeometry = {contentsRect.left(), contentsRect.top(), + _lineNumArea->sizeHint().width(), + contentsRect.height()}; + auto oldGeometry = _lineNumArea->geometry(); + if (newGeometry != oldGeometry) { + _lineNumArea->setGeometry(newGeometry); + } +} + +void QMarkdownTextEdit::resizeEvent(QResizeEvent *event) { + QPlainTextEdit::resizeEvent(event); + updateLineNumAreaGeometry(); +} + /** * Increases (or decreases) the indention of the selected text * (if there is a text selected) in the noteTextEdit * @return */ -bool QMarkdownTextEdit::increaseSelectedTextIndention(bool reverse) { +bool QMarkdownTextEdit::increaseSelectedTextIndention( + bool reverse, const QString &indentCharacters) { QTextCursor cursor = this->textCursor(); QString selectedText = cursor.selectedText(); - if (selectedText != "") { + if (!selectedText.isEmpty()) { + // Start the selection at start of the first block of the selection + int end = cursor.selectionEnd(); + cursor.setPosition(cursor.selectionStart()); + cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor); + cursor.setPosition(end, QTextCursor::KeepAnchor); + this->setTextCursor(cursor); + selectedText = cursor.selectedText(); + // we need this strange newline character we are getting in the // selected text for newlines - QString newLine = QString::fromUtf8(QByteArray::fromHex("e280a9")); + const QString newLine = + QString::fromUtf8(QByteArray::fromHex(QByteArrayLiteral("e280a9"))); QString newText; if (reverse) { // un-indent text - // remove strange newline characters - newText = selectedText.replace( - QRegularExpression(newLine + "[\\t ]"), "\n"); + const int indentSize = indentCharacters == QStringLiteral("\t") + ? 4 + : indentCharacters.length(); - // remove leading \t or space - newText.remove(QRegularExpression("^[\\t ]")); + // remove leading \t or spaces in following lines + newText = selectedText.replace( + QRegularExpression(newLine + QStringLiteral("(\\t| {1,") + + QString::number(indentSize) + + QStringLiteral("})")), + QStringLiteral("\n")); + + // remove leading \t or spaces in first line + newText.remove(QRegularExpression(QStringLiteral("^(\\t| {1,") + + QString::number(indentSize) + + QStringLiteral("})"))); } else { + // replace trailing new line to prevent an indent of the line after + // the selection + newText = selectedText.replace( + QRegularExpression(QRegularExpression::escape(newLine) + + QStringLiteral("$")), + QStringLiteral("\n")); + // indent text - newText = selectedText.replace(newLine, "\n\t").prepend("\t"); + newText.replace(newLine, QStringLiteral("\n") + indentCharacters) + .prepend(indentCharacters); // remove trailing \t - newText.replace(QRegularExpression("\\t$"), ""); + static QRegularExpression regex1(QStringLiteral("\\t$")); + newText.remove(regex1); } // insert the new text cursor.insertText(newText); // update the selection to the new text - cursor.setPosition(cursor.position() - newText.size(), QTextCursor::KeepAnchor); + cursor.setPosition(cursor.position() - newText.size(), + QTextCursor::KeepAnchor); this->setTextCursor(cursor); return true; } else if (reverse) { - // if nothing was selected but we want to reverse the indention check - // if there is a \t in front or after the cursor and remove it if so - int position = cursor.position(); + const int indentSize = indentCharacters.length(); - if (!cursor.atStart()) { - // get character in front of cursor - cursor.setPosition(position - 1, QTextCursor::KeepAnchor); - } + // do the check as often as we have characters to un-indent + for (int i = 1; i <= indentSize; i++) { + // if nothing was selected but we want to reverse the indention + // check if there is a \t in front or after the cursor and remove it + // if so + const int position = cursor.position(); - // check for \t or space in front of cursor - QRegularExpression re("[\\t ]"); - QRegularExpressionMatch match = re.match(cursor.selectedText()); - - if (!match.hasMatch()) { - // (select to) check for \t or space after the cursor - cursor.setPosition(position); - - if (!cursor.atEnd()) { - cursor.setPosition(position + 1, QTextCursor::KeepAnchor); + if (!cursor.atStart()) { + // get character in front of cursor + cursor.setPosition(position - 1, QTextCursor::KeepAnchor); } - } - match = re.match(cursor.selectedText()); + // check for \t or space in front of cursor + static QRegularExpression regex1(QStringLiteral("[\\t ]")); + QRegularExpressionMatch match = regex1.match(cursor.selectedText()); - if (match.hasMatch()) { - cursor.removeSelectedText(); + if (!match.hasMatch()) { + // (select to) check for \t or space after the cursor + cursor.setPosition(position); + + if (!cursor.atEnd()) { + cursor.setPosition(position + 1, QTextCursor::KeepAnchor); + } + } + + match = regex1.match(cursor.selectedText()); + + if (match.hasMatch()) { + cursor.removeSelectedText(); + } + + cursor = this->textCursor(); } return true; } - return false; + // else just insert indentCharacters + cursor.insertText(indentCharacters); + + return true; } /** @@ -681,31 +1195,34 @@ bool QMarkdownTextEdit::increaseSelectedTextIndention(bool reverse) { */ bool QMarkdownTextEdit::openLinkAtCursorPosition() { QTextCursor cursor = this->textCursor(); - int clickedPosition = cursor.position(); + const int clickedPosition = cursor.position(); // select the text in the clicked block and find out on // which position we clicked cursor.movePosition(QTextCursor::StartOfBlock); - int positionFromStart = clickedPosition - cursor.position(); + const int positionFromStart = clickedPosition - cursor.position(); cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - QString selectedText = cursor.selectedText(); + const QString selectedText = cursor.selectedText(); // find out which url in the selected text was clicked - QString urlString = getMarkdownUrlAtPosition(selectedText, - positionFromStart); - QUrl url = QUrl(urlString); - bool isRelativeFileUrl = urlString.startsWith("file://.."); + const QString urlString = + getMarkdownUrlAtPosition(selectedText, positionFromStart); + const QUrl url = QUrl(urlString); + const bool isRelativeFileUrl = + urlString.startsWith(QLatin1String("file://..")); + const bool isLegacyAttachmentUrl = + urlString.startsWith(QLatin1String("file://attachments")); - qDebug() << __func__ << " - 'emit urlClicked( urlString )': " - << urlString; + qDebug() << __func__ << " - 'emit urlClicked( urlString )': " << urlString; - emit urlClicked(urlString); + Q_EMIT urlClicked(urlString); - if ((url.isValid() && isValidUrl(urlString)) || isRelativeFileUrl) { + if ((url.isValid() && isValidUrl(urlString)) || isRelativeFileUrl || + isLegacyAttachmentUrl) { // ignore some schemata if (!(_ignoredClickUrlSchemata.contains(url.scheme()) || - isRelativeFileUrl)) { + isRelativeFileUrl || isLegacyAttachmentUrl)) { // open the url openUrl(urlString); } @@ -722,9 +1239,9 @@ bool QMarkdownTextEdit::openLinkAtCursorPosition() { * @param urlString * @return */ -bool QMarkdownTextEdit::isValidUrl(QString urlString) { - QRegularExpressionMatch match = - QRegularExpression("^\\w+:\\/\\/.+").match(urlString); +bool QMarkdownTextEdit::isValidUrl(const QString &urlString) { + static QRegularExpression regex(R"(^\w+:\/\/.+)"); + const QRegularExpressionMatch match = regex.match(urlString); return match.hasMatch(); } @@ -737,9 +1254,9 @@ bool QMarkdownTextEdit::isValidUrl(QString urlString) { * "/path/to/my/file/QOwnNotes.pdf" if the operating system supports that * handler */ -void QMarkdownTextEdit::openUrl(QString urlString) { - qDebug() << "QMarkdownTextEdit " << __func__ << " - 'urlString': " - << urlString; +void QMarkdownTextEdit::openUrl(const QString &urlString) { + qDebug() << "QMarkdownTextEdit " << __func__ + << " - 'urlString': " << urlString; QDesktopServices::openUrl(QUrl(urlString)); } @@ -748,9 +1265,7 @@ void QMarkdownTextEdit::openUrl(QString urlString) { * @brief Returns the highlighter instance * @return */ -MarkdownHighlighter *QMarkdownTextEdit::highlighter() { - return _highlighter; -} +MarkdownHighlighter *QMarkdownTextEdit::highlighter() { return _highlighter; } /** * @brief Returns the searchWidget instance @@ -765,26 +1280,25 @@ QPlainTextEditSearchWidget *QMarkdownTextEdit::searchWidget() { * @param urlSchemes */ void QMarkdownTextEdit::setIgnoredClickUrlSchemata( - QStringList ignoredUrlSchemata) { - _ignoredClickUrlSchemata = ignoredUrlSchemata; + QStringList ignoredUrlSchemata) { + _ignoredClickUrlSchemata = std::move(ignoredUrlSchemata); } /** - * @brief Returns a map of parsed markdown urls with their link texts as key + * @brief Returns a map of parsed Markdown urls with their link texts as key * * @param text * @return parsed urls */ QMap QMarkdownTextEdit::parseMarkdownUrlsFromText( - QString text) { + const QString &text) { QMap urlMap; - QRegularExpression regex; QRegularExpressionMatchIterator iterator; // match urls like this: -// re = QRegularExpression("(<(.+?:\\/\\/.+?)>)"); - regex = QRegularExpression("(<(.+?)>)"); - iterator = regex.globalMatch(text); + // re = QRegularExpression("(<(.+?:\\/\\/.+?)>)"); + static QRegularExpression regex1(QStringLiteral("(<(.+?)>)")); + iterator = regex1.globalMatch(text); while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); QString linkText = match.captured(1); @@ -793,9 +1307,9 @@ QMap QMarkdownTextEdit::parseMarkdownUrlsFromText( } // match urls like this: [this url](http://mylink) -// QRegularExpression re("(\\[.*?\\]\\((.+?:\\/\\/.+?)\\))"); - regex = QRegularExpression("(\\[.*?\\]\\((.+?)\\))"); - iterator = regex.globalMatch(text); + // QRegularExpression re("(\\[.*?\\]\\((.+?:\\/\\/.+?)\\))"); + static QRegularExpression regex2(R"((\[.*?\]\((.+?)\)))"); + iterator = regex2.globalMatch(text); while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); QString linkText = match.captured(1); @@ -804,29 +1318,39 @@ QMap QMarkdownTextEdit::parseMarkdownUrlsFromText( } // match urls like this: http://mylink - regex = QRegularExpression("\\b\\w+?:\\/\\/[^\\s]+[^\\s>\\)]"); - iterator = regex.globalMatch(text); + static QRegularExpression regex3(R"(\b\w+?:\/\/[^\s]+[^\s>\)])"); + iterator = regex3.globalMatch(text); while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); QString url = match.captured(0); urlMap[url] = url; } + // match urls like this: www.github.com + static QRegularExpression regex4(R"(\bwww\.[^\s]+\.[^\s]+\b)"); + iterator = regex4.globalMatch(text); + while (iterator.hasNext()) { + QRegularExpressionMatch match = iterator.next(); + QString url = match.captured(0); + urlMap[url] = QStringLiteral("http://") + url; + } + // match reference urls like this: [this url][1] with this later: // [1]: http://domain - regex = QRegularExpression("\\[(.*?)\\]\\s?\\[(.+?)\\]"); - iterator = regex.globalMatch(text); + static QRegularExpression regex5(R"((\[.*?\]\[(.+?)\]))"); + iterator = regex5.globalMatch(text); while (iterator.hasNext()) { QRegularExpressionMatch match = iterator.next(); QString linkText = match.captured(1); QString referenceId = match.captured(2); // search for the referenced url in the whole text edit -// QRegularExpression refRegExp( -// "\\[" + QRegularExpression::escape(referenceId) + -// "\\]: (.+?:\\/\\/.+)"); - QRegularExpression refRegExp( - "\\[" + QRegularExpression::escape(referenceId) + "\\]: (.+?)"); + // QRegularExpression refRegExp( + // "\\[" + QRegularExpression::escape(referenceId) + + // "\\]: (.+?:\\/\\/.+)"); + QRegularExpression refRegExp(QStringLiteral("\\[") + + QRegularExpression::escape(referenceId) + + QStringLiteral("\\]: (.+)")); QRegularExpressionMatch urlMatch = refRegExp.match(toPlainText()); if (urlMatch.hasMatch()) { @@ -839,29 +1363,27 @@ QMap QMarkdownTextEdit::parseMarkdownUrlsFromText( } /** - * @brief Returns the markdown url at position + * @brief Returns the Markdown url at position * @param text * @param position * @return url string */ -QString QMarkdownTextEdit::getMarkdownUrlAtPosition( - QString text, int position) { +QString QMarkdownTextEdit::getMarkdownUrlAtPosition(const QString &text, + int position) { QString url; - // get a map of parsed markdown urls with their link texts as key - QMap urlMap = parseMarkdownUrlsFromText(text); + // get a map of parsed Markdown urls with their link texts as key + const QMap urlMap = parseMarkdownUrlsFromText(text); + QMap::const_iterator i = urlMap.constBegin(); + for (; i != urlMap.constEnd(); ++i) { + const QString &linkText = i.key(); + const QString &urlString = i.value(); - QMapIterator iterator(urlMap); - while (iterator.hasNext()) { - iterator.next(); - QString linkText = iterator.key(); - QString urlString = iterator.value(); - - int foundPositionStart = text.indexOf(linkText); + const int foundPositionStart = text.indexOf(linkText); if (foundPositionStart >= 0) { // calculate end position of found linkText - int foundPositionEnd = foundPositionStart + linkText.size(); + const int foundPositionEnd = foundPositionStart + linkText.size(); // check if position is in found string range if ((position >= foundPositionStart) && @@ -879,18 +1401,22 @@ QString QMarkdownTextEdit::getMarkdownUrlAtPosition( * @brief Duplicates the text in the text edit */ void QMarkdownTextEdit::duplicateText() { + if (isReadOnly()) { + return; + } + QTextCursor cursor = this->textCursor(); QString selectedText = cursor.selectedText(); // duplicate line if no text was selected - if (selectedText == "") { - int position = cursor.position(); + if (selectedText.isEmpty()) { + const int position = cursor.position(); // select the whole line - cursor.movePosition(QTextCursor::StartOfLine); - cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::StartOfBlock); + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - int positionDiff = cursor.position() - position; + const int positionDiff = cursor.position() - position; selectedText = "\n" + cursor.selectedText(); // insert text with new line at end of the selected line @@ -902,11 +1428,11 @@ void QMarkdownTextEdit::duplicateText() { } else { // duplicate selected text cursor.setPosition(cursor.selectionEnd()); - int selectionStart = cursor.position(); + const int selectionStart = cursor.position(); // insert selected text cursor.insertText(selectedText); - int selectionEnd = cursor.position(); + const int selectionEnd = cursor.position(); // select the inserted text cursor.setPosition(selectionStart); @@ -916,21 +1442,19 @@ void QMarkdownTextEdit::duplicateText() { this->setTextCursor(cursor); } -void QMarkdownTextEdit::setText(const QString & text) { - setPlainText(text); -} +void QMarkdownTextEdit::setText(const QString &text) { setPlainText(text); } -void QMarkdownTextEdit::setPlainText(const QString & text) { +void QMarkdownTextEdit::setPlainText(const QString &text) { // clear the dirty blocks vector to increase performance and prevent // a possible crash in QSyntaxHighlighter::rehighlightBlock - _highlighter->clearDirtyBlocks(); + if (_highlighter) _highlighter->clearDirtyBlocks(); QPlainTextEdit::setPlainText(text); adjustRightMargin(); } /** - * Uses an other widget as parent for the search widget + * Uses another widget as parent for the search widget */ void QMarkdownTextEdit::initSearchFrame(QWidget *searchFrame, bool darkMode) { _searchFrame = searchFrame; @@ -941,8 +1465,8 @@ void QMarkdownTextEdit::initSearchFrame(QWidget *searchFrame, bool darkMode) { QLayout *layout = _searchFrame->layout(); // create a grid layout for the frame and add the search widget to it - if (layout == NULL) { - layout = new QVBoxLayout(); + if (layout == nullptr) { + layout = new QVBoxLayout(_searchFrame); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); } @@ -964,44 +1488,153 @@ void QMarkdownTextEdit::hide() { * Handles an entered return key */ bool QMarkdownTextEdit::handleReturnEntered() { + if (isReadOnly()) { + return true; + } + + // This will be the main cursor to add or remove text QTextCursor cursor = this->textCursor(); - int position = cursor.position(); + // We need a 2nd cursor to get the text of the current block without moving + // the main cursor that is used to remove the selected text + QTextCursor cursor2 = this->textCursor(); + cursor2.select(QTextCursor::BlockUnderCursor); + const QString currentLineText = cursor2.selectedText().trimmed(); + + const int position = cursor.position(); + const bool cursorAtBlockStart = cursor.atBlockStart(); cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); - QString currentLineText = cursor.selectedText(); + const QString currentLinePartialText = cursor.selectedText(); - // if return is pressed and there is just a list symbol then we want to - // remove the list symbol - // Valid listCharacters: '+ ', '-' , '* ', '+ [ ] ', '+ [x] ', '- [ ] ', '- [x] ', '* [ ] ', '* [x] '. - QRegularExpression regex("^(\\s*)([+|\\-|\\*] \\[(x| )\\]|[+\\-\\*])(\\s+)$"); - QRegularExpressionMatchIterator iterator = regex.globalMatch(currentLineText); + // if return is pressed and there is just an unordered list symbol then we + // want to remove the list symbol Valid listCharacters: '+ ', '-' , '* ', '+ + // [ ] ', '+ [x] ', '- [ ] ', '- [-] ', '- [x] ', '* [ ] ', '* [x] '. + static QRegularExpression regex1( + R"(^(\s*)([+|\-|\*] \[(x|-| |)\]|[+\-\*])(\s+)$)"); + QRegularExpressionMatchIterator iterator = + regex1.globalMatch(currentLinePartialText); if (iterator.hasNext()) { cursor.removeSelectedText(); return true; } - // Check if we are in a list. + // if return is pressed and there is just an ordered list symbol then we + // want to remove the list symbol + static QRegularExpression regex2(R"(^(\s*)(\d+[\.|\)])(\s+)$)"); + iterator = regex2.globalMatch(currentLinePartialText); + if (iterator.hasNext()) { + qDebug() << cursor.selectedText(); + cursor.removeSelectedText(); + return true; + } + + // Check if we are in an unordered list. // We are in a list when we have '* ', '- ' or '+ ', possibly with preceding // whitespace. If e.g. user has entered '**text**' and pressed enter - we - // don't want do anymore list-stuff. - QChar char0 = currentLineText.trimmed()[0]; - QChar char1 = currentLineText.trimmed()[1]; - bool inList = ((char0 == '*' || char0 == '-' || char0 == '+') && char1 == ' '); + // don't want to do more list-stuff. + QString currentLine = currentLinePartialText.trimmed(); + QChar char0; + QChar char1; + if (currentLine.length() >= 1) char0 = currentLine.at(0); + if (currentLine.length() >= 2) char1 = currentLine.at(1); + const bool inList = + ((char0 == QLatin1Char('*') || char0 == QLatin1Char('-') || + char0 == QLatin1Char('+')) && + char1 == QLatin1Char(' ')); if (inList) { // if the current line starts with a list character (possibly after // whitespaces) add the whitespaces at the next line too - // Valid listCharacters: '+ ', '-' , '* ', '+ [ ] ', '+ [x] ', '- [ ] ', '- [x] ', '* [ ] ', '* [x] '. - regex = QRegularExpression("^(\\s*)([+|\\-|\\*] \\[(x| )\\]|[+\\-\\*])(\\s+)"); - iterator = regex.globalMatch(currentLineText); + // Valid listCharacters: '+ ', '-' , '* ', '+ [ ] ', '+ [x] ', '- [ ] ', + // '- [x] ', '- [-] ', '* [ ] ', '* [x] '. + static QRegularExpression regex3( + R"(^(\s*)([+|\-|\*] \[(x|-| |)\]|[+\-\*])(\s+))"); + iterator = regex3.globalMatch(currentLinePartialText); if (iterator.hasNext()) { - QRegularExpressionMatch match = iterator.next(); - QString whitespaces = match.captured(1); + const QRegularExpressionMatch match = iterator.next(); + const QString whitespaces = match.captured(1); QString listCharacter = match.captured(2); - QString whitespaceCharacter = match.captured(4); + const QString whitespaceCharacter = match.captured(4); + + static QRegularExpression regex4(R"(^([+|\-|\*]) \[(x| |\-|)\])"); + // start new checkbox list item with an unchecked checkbox + iterator = regex4.globalMatch(listCharacter); + if (iterator.hasNext()) { + const QRegularExpressionMatch match1 = iterator.next(); + const QString realListCharacter = match1.captured(1); + listCharacter = realListCharacter + QStringLiteral(" [ ]"); + } cursor.setPosition(position); - cursor.insertText("\n" + whitespaces + listCharacter + whitespaceCharacter); + cursor.insertText("\n" + whitespaces + listCharacter + + whitespaceCharacter); + + // scroll to the cursor if we are at the bottom of the document + ensureCursorVisible(); + return true; + } + } + + // check for ordered lists and increment the list number in the next line + static QRegularExpression regex5(R"(^(\s*)(\d+)([\.|\)])(\s+))"); + iterator = regex5.globalMatch(currentLinePartialText); + if (iterator.hasNext()) { + const QRegularExpressionMatch match = iterator.next(); + const QString whitespaces = match.captured(1); + const uint listNumber = match.captured(2).toUInt(); + const QString listMarker = match.captured(3); + const QString whitespaceCharacter = match.captured(4); + + cursor.setPosition(position); + cursor.insertText("\n" + whitespaces + QString::number(listNumber + 1) + + listMarker + whitespaceCharacter); + + // scroll to the cursor if we are at the bottom of the document + ensureCursorVisible(); + return true; + } + + // intent next line with same whitespaces as in current line + static QRegularExpression regex6(R"(^(\s+))"); + iterator = regex6.globalMatch(currentLinePartialText); + if (iterator.hasNext()) { + const QRegularExpressionMatch match = iterator.next(); + const QString whitespaces = match.captured(1); + + cursor.setPosition(position); + cursor.insertText("\n" + whitespaces); + + // scroll to the cursor if we are at the bottom of the document + ensureCursorVisible(); + return true; + } + + // Add new list item above current line if we are at the start the line of a + // list item + if (cursorAtBlockStart) { + static QRegularExpression regex7( + R"(^([+|\-|\*] \[(x|-| |)\]|[+\-\*])(\s+))"); + iterator = regex7.globalMatch(currentLineText); + if (iterator.hasNext()) { + const QRegularExpressionMatch match = iterator.next(); + QString listCharacter = match.captured(1); + const QString whitespaceCharacter = match.captured(3); + + static QRegularExpression regex8(R"(^([+|\-|\*]) \[(x| |\-|)\])"); + // start new checkbox list item with an unchecked checkbox + iterator = regex8.globalMatch(listCharacter); + if (iterator.hasNext()) { + const QRegularExpressionMatch match1 = iterator.next(); + const QString realListCharacter = match1.captured(1); + listCharacter = realListCharacter + QStringLiteral(" [ ]"); + } + + cursor.setPosition(position); + // Enter new list item above current line + cursor.insertText(listCharacter + whitespaceCharacter + "\n"); + // Move the cursor at the end of the new list item + cursor.movePosition(QTextCursor::Left); + setTextCursor(cursor); // scroll to the cursor if we are at the bottom of the document ensureCursorVisible(); @@ -1015,39 +1648,75 @@ bool QMarkdownTextEdit::handleReturnEntered() { /** * Handles entered tab or reverse tab keys */ -bool QMarkdownTextEdit::handleTabEntered(bool reverse) { +bool QMarkdownTextEdit::handleTabEntered(bool reverse, + const QString &indentCharacters) { + if (isReadOnly()) { + return true; + } + QTextCursor cursor = this->textCursor(); // only check for lists if we haven't a text selected if (cursor.selectedText().isEmpty()) { - cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); - QString currentLineText = cursor.selectedText(); + cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); + const QString currentLineText = cursor.selectedText(); - // check if we want to indent or un-indent a list - // Valid listCharacters: '+ ', '-' , '* ', '+ [ ] ', '+ [x] ', '- [ ] ', '- [x] ', '* [ ] ', '* [x] '. - QRegularExpression re("^(\\s*)([+|\\-|\\*] \\[(x| )\\]|[+\\-\\*])(\\s+)$"); - QRegularExpressionMatchIterator i = re.globalMatch(currentLineText); + // check if we want to indent or un-indent an ordered list + // Valid listCharacters: '+ ', '-' , '* ', '+ [ ] ', '+ [x] ', '- [ ] ', + // '- [x] ', '- [-] ', '* [ ] ', '* [x] '. + static QRegularExpression regex1( + R"(^(\s*)([+|\-|\*] \[(x|-| )\]|[+\-\*])(\s+)$)"); + QRegularExpressionMatchIterator i = regex1.globalMatch(currentLineText); if (i.hasNext()) { QRegularExpressionMatch match = i.next(); QString whitespaces = match.captured(1); - QString listCharacter = match.captured(2); - QString whitespaceCharacter = match.captured(4); + const QString listCharacter = match.captured(2); + const QString whitespaceCharacter = match.captured(4); + + // add or remove one tabulator key + if (reverse) { + // remove one set of indentCharacters or a tabulator + whitespaces.remove(QRegularExpression( + QStringLiteral("^(\\t|") + + QRegularExpression::escape(indentCharacters) + + QStringLiteral(")"))); + + } else { + whitespaces += indentCharacters; + } + + cursor.insertText(whitespaces + listCharacter + + whitespaceCharacter); + return true; + } + + // check if we want to indent or un-indent an ordered list + static QRegularExpression regex2(R"(^(\s*)(\d+)([\.|\)])(\s+)$)"); + i = regex2.globalMatch(currentLineText); + + if (i.hasNext()) { + const QRegularExpressionMatch match = i.next(); + QString whitespaces = match.captured(1); + const QString listCharacter = match.captured(2); + const QString listMarker = match.captured(3); + const QString whitespaceCharacter = match.captured(4); // add or remove one tabulator key if (reverse) { whitespaces.chop(1); } else { - whitespaces += "\t"; + whitespaces += indentCharacters; } - cursor.insertText(whitespaces + listCharacter + whitespaceCharacter); + cursor.insertText(whitespaces + listCharacter + listMarker + + whitespaceCharacter); return true; } } - // check if we want to intent the whole text - return increaseSelectedTextIndention(reverse); + // check if we want to indent the whole text + return increaseSelectedTextIndention(reverse, indentCharacters); } /** @@ -1057,30 +1726,189 @@ void QMarkdownTextEdit::setAutoTextOptions(AutoTextOptions options) { _autoTextOptions = options; } +void QMarkdownTextEdit::updateLineNumberArea(const QRect rect, int dy) { + if (dy) + _lineNumArea->scroll(0, dy); + else + _lineNumArea->update(0, rect.y(), _lineNumArea->sizeHint().width(), + rect.height()); + + updateLineNumAreaGeometry(); + + if (rect.contains(viewport()->rect())) { + updateLineNumberAreaWidth(0); + } +} + +void QMarkdownTextEdit::updateLineNumberAreaWidth(int) { + QSignalBlocker blocker(this); + const auto oldMargins = viewportMargins(); + const int width = + _lineNumArea->isLineNumAreaEnabled() + ? _lineNumArea->sizeHint().width() + _lineNumberLeftMarginOffset + : oldMargins.left(); + const auto newMargins = QMargins{width, oldMargins.top(), + oldMargins.right(), oldMargins.bottom()}; + + if (newMargins != oldMargins) { + setViewportMargins(newMargins); + } + + // Grow lineNumArea font-size with the font size of the editor + const int pointSize = this->font().pointSize(); + if (pointSize > 0) { + QFont font = _lineNumArea->font(); + font.setPointSize(pointSize); + _lineNumArea->setFont(font); + } +} + /** - * Overrides QPlainTextEdit::paintEvent to fix the RTL bug of QPlainTextEdit - * * @param e + * @details This does two things + * 1. Overrides QPlainTextEdit::paintEvent to fix the RTL bug of QPlainTextEdit + * 2. Paints a rectangle around code block fences [Code taken from + * ghostwriter(which in turn is based on QPlaintextEdit::paintEvent() with + * modifications and minor improvements for our use */ void QMarkdownTextEdit::paintEvent(QPaintEvent *e) { QTextBlock block = firstVisibleBlock(); - while (block.isValid()) { - QTextLayout *layout = block.layout(); + QPainter painter(viewport()); + const QRect viewportRect = viewport()->rect(); + // painter.fillRect(viewportRect, Qt::transparent); + bool firstVisible = true; + QPointF offset(contentOffset()); + QRectF blockAreaRect; // Code or block quote rect. + bool inBlockArea = false; + + bool clipTop = false; + bool drawBlock = false; + qreal dy = 0.0; + bool done = false; + + const QColor &color = MarkdownHighlighter::codeBlockBackgroundColor(); + const int cornerRadius = 5; + + while (block.isValid() && !done) { + const QRectF r = blockBoundingRect(block).translated(offset); + const int state = block.userState(); + + if (!inBlockArea && MarkdownHighlighter::isCodeBlock(state)) { + // skip the backticks + if (!block.text().startsWith(QLatin1String("```")) && + !block.text().startsWith(QLatin1String("~~~"))) { + blockAreaRect = r; + dy = 0.0; + inBlockArea = true; + } + + // If this is the first visible block within the viewport + // and if the previous block is part of the text block area, + // then the rectangle to draw for the block area will have + // its top clipped by the viewport and will need to be + // drawn specially. + const int prevBlockState = block.previous().userState(); + if (firstVisible && + MarkdownHighlighter::isCodeBlock(prevBlockState)) { + clipTop = true; + } + } + // Else if the block ends a text block area... + else if (inBlockArea && MarkdownHighlighter::isCodeBlockEnd(state)) { + drawBlock = true; + inBlockArea = false; + blockAreaRect.setHeight(dy); + } + // If the block is at the end of the document and ends a text + // block area... + // + if (inBlockArea && block == this->document()->lastBlock()) { + drawBlock = true; + inBlockArea = false; + dy += r.height(); + blockAreaRect.setHeight(dy); + } + offset.ry() += r.height(); + dy += r.height(); + + // If this is the last text block visible within the viewport... + if (offset.y() > viewportRect.height()) { + if (inBlockArea) { + blockAreaRect.setHeight(dy); + drawBlock = true; + } + + // Finished drawing. + done = true; + } + // If this is the last text block visible within the viewport... + if (offset.y() > viewportRect.height()) { + if (inBlockArea) { + blockAreaRect.setHeight(dy); + drawBlock = true; + } + // Finished drawing. + done = true; + } + + if (drawBlock) { + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + painter.setPen(Qt::NoPen); + painter.setBrush(QBrush(color)); + + // If the first visible block is "clipped" such that the previous + // block is part of the text block area, then only draw a rectangle + // with the bottom corners rounded, and with the top corners square + // to reflect that the first visible block is part of a larger block + // of text. + // + if (clipTop) { + QPainterPath path; + path.setFillRule(Qt::WindingFill); + path.addRoundedRect(blockAreaRect, cornerRadius, cornerRadius); + qreal adjustedHeight = blockAreaRect.height() / 2; + path.addRect(blockAreaRect.adjusted(0, 0, 0, -adjustedHeight)); + painter.drawPath(path.simplified()); + clipTop = false; + } + // Else draw the entire rectangle with all corners rounded. + else { + painter.drawRoundedRect(blockAreaRect, cornerRadius, + cornerRadius); + } + + drawBlock = false; + } // this fixes the RTL bug of QPlainTextEdit // https://bugreports.qt.io/browse/QTBUG-7516 - if (block.text().isRightToLeft()) - { - QTextOption opt = document()->defaultTextOption(); - opt = QTextOption(Qt::AlignRight); + if (block.text().isRightToLeft()) { + QTextLayout *layout = block.layout(); + // opt = document()->defaultTextOption(); + QTextOption opt = QTextOption(Qt::AlignRight); opt.setTextDirection(Qt::RightToLeft); layout->setTextOption(opt); } + // Current line highlight + QTextCursor cursor = textCursor(); + if (highlightCurrentLine() && cursor.block() == block) { + QTextLine line = + block.layout()->lineForTextPosition(cursor.positionInBlock()); + QRectF lineRect = line.rect(); + lineRect.moveTop(lineRect.top() + r.top()); + lineRect.setLeft(0.); + lineRect.setRight(viewportRect.width()); + painter.fillRect(lineRect.toAlignedRect(), + currentLineHighlightColor()); + } + block = block.next(); + firstVisible = false; } + painter.end(); QPlainTextEdit::paintEvent(e); } @@ -1097,3 +1925,33 @@ void QMarkdownTextEdit::setReadOnly(bool ro) { // @see https://github.com/pbek/QOwnNotes/issues/976 setAttribute(Qt::WA_InputMethodEnabled, !isReadOnly()); } + +void QMarkdownTextEdit::doSearch( + QString &searchText, QPlainTextEditSearchWidget::SearchMode searchMode) { + _searchWidget->setSearchText(searchText); + _searchWidget->setSearchMode(searchMode); + _searchWidget->doSearchCount(); + _searchWidget->activate(false); +} + +void QMarkdownTextEdit::hideSearchWidget(bool reset) { + _searchWidget->deactivate(); + + if (reset) { + _searchWidget->reset(); + } +} + +void QMarkdownTextEdit::updateSettings() { + // if true: centers the screen if cursor reaches bottom (but not top) + searchWidget()->setDebounceDelay(_debounceDelay); + setCenterOnScroll(_centerCursor); +} + +void QMarkdownTextEdit::setLineNumberLeftMarginOffset(int offset) { + _lineNumberLeftMarginOffset = offset; +} + +QMargins QMarkdownTextEdit::viewportMargins() { + return QPlainTextEdit::viewportMargins(); +} diff --git a/client/qmarkdowntextedit/qmarkdowntextedit.h b/client/qmarkdowntextedit/qmarkdowntextedit.h index 5463f70..1ab56d7 100644 --- a/client/qmarkdowntextedit/qmarkdowntextedit.h +++ b/client/qmarkdowntextedit/qmarkdowntextedit.h @@ -1,87 +1,144 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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. */ #pragma once -#include #include +#include + #include "markdownhighlighter.h" #include "qplaintexteditsearchwidget.h" +class LineNumArea; -class QMarkdownTextEdit : public QPlainTextEdit -{ +class QMarkdownTextEdit : public QPlainTextEdit { Q_OBJECT + Q_PROPERTY( + bool highlighting READ highlightingEnabled WRITE setHighlightingEnabled) -public: + friend class LineNumArea; + + public: enum AutoTextOption { None = 0x0000, - // inserts closing characters for brackets and markdown characters + // inserts closing characters for brackets and Markdown characters BracketClosing = 0x0001, - // removes matching brackets and markdown characters + // removes matching brackets and Markdown characters BracketRemoval = 0x0002 }; Q_DECLARE_FLAGS(AutoTextOptions, AutoTextOption) - explicit QMarkdownTextEdit(QWidget *parent = 0, bool initHighlighter = true); + explicit QMarkdownTextEdit(QWidget *parent = nullptr, + bool initHighlighter = true); MarkdownHighlighter *highlighter(); QPlainTextEditSearchWidget *searchWidget(); void setIgnoredClickUrlSchemata(QStringList ignoredUrlSchemata); - virtual void openUrl(QString urlString); - QString getMarkdownUrlAtPosition(QString text, int position); + virtual void openUrl(const QString &urlString); + QString getMarkdownUrlAtPosition(const QString &text, int position); void initSearchFrame(QWidget *searchFrame, bool darkMode = false); void setAutoTextOptions(AutoTextOptions options); - void setHighlightingEnabled(bool enabled); - static bool isValidUrl(QString urlString); + static bool isValidUrl(const QString &urlString); void resetMouseCursor() const; void setReadOnly(bool ro); + void doSearch(QString &searchText, + QPlainTextEditSearchWidget::SearchMode searchMode = + QPlainTextEditSearchWidget::SearchMode::PlainTextMode); + void hideSearchWidget(bool reset); + void updateSettings(); + void setLineNumbersCurrentLineColor(QColor color); + void setLineNumbersOtherLineColor(QColor color); + void setSearchWidgetDebounceDelay(uint debounceDelay); -public slots: + void setHighlightingEnabled(bool enabled); + [[nodiscard]] bool highlightingEnabled() const; + + void setHighlightCurrentLine(bool set); + bool highlightCurrentLine(); + + void setCurrentLineHighlightColor(const QColor &c); + QColor currentLineHighlightColor(); + + public Q_SLOTS: void duplicateText(); - void setText(const QString & text); - void setPlainText(const QString & text); + void setText(const QString &text); + void setPlainText(const QString &text); void adjustRightMargin(); void hide(); bool openLinkAtCursorPosition(); - bool handleBracketRemoval(); + bool handleBackspaceEntered(); + void centerTheCursor(); + void undo(); + void moveTextUpDown(bool up); + void setLineNumberEnabled(bool enabled); -protected: - MarkdownHighlighter *_highlighter; + protected: + QTextCursor _textCursor; + MarkdownHighlighter *_highlighter = nullptr; bool _highlightingEnabled; QStringList _ignoredClickUrlSchemata; QPlainTextEditSearchWidget *_searchWidget; QWidget *_searchFrame; AutoTextOptions _autoTextOptions; - QStringList _openingCharacters; - QStringList _closingCharacters; + bool _mouseButtonDown = false; + bool _centerCursor = false; + bool _highlightCurrentLine = false; + QColor _currentLineHighlightColor = QColor(); + uint _debounceDelay = 0; - bool eventFilter(QObject *obj, QEvent *event); - bool increaseSelectedTextIndention(bool reverse); - bool handleTabEntered(bool reverse); - QMap parseMarkdownUrlsFromText(QString text); + bool eventFilter(QObject *obj, QEvent *event) override; + QMargins viewportMargins(); + bool increaseSelectedTextIndention( + bool reverse, + const QString &indentCharacters = QChar::fromLatin1('\t')); + bool handleTabEntered(bool reverse, const QString &indentCharacters = + QChar::fromLatin1('\t')); + QMap parseMarkdownUrlsFromText(const QString &text); bool handleReturnEntered(); - bool handleBracketClosing(QString openingCharacter, - QString closingCharacter = ""); - bool bracketClosingCheck(QString openingCharacter, - QString closingCharacter); - bool quotationMarkCheck(QString quotationCharacter); - void focusOutEvent(QFocusEvent *event); - void paintEvent(QPaintEvent *e); + bool handleBracketClosing(const QChar openingCharacter, + QChar closingCharacter = QChar()); + bool bracketClosingCheck(const QChar openingCharacter, + QChar closingCharacter); + bool quotationMarkCheck(const QChar quotationCharacter); + void focusOutEvent(QFocusEvent *event) override; + void paintEvent(QPaintEvent *e) override; + bool handleCharRemoval(MarkdownHighlighter::RangeType type, int block, + int position); + void resizeEvent(QResizeEvent *event) override; + void setLineNumberLeftMarginOffset(int offset); + int _lineNumberLeftMarginOffset = 0; + LineNumArea *lineNumberArea() { return _lineNumArea; } + void updateLineNumAreaGeometry(); + void updateLineNumberArea(const QRect rect, int dy); + Q_SLOT void updateLineNumberAreaWidth(int); + bool _handleBracketClosingUsed; + LineNumArea *_lineNumArea; -signals: + Q_SIGNALS: void urlClicked(QString url); + void zoomIn(); + void zoomOut(); }; diff --git a/client/qmarkdowntextedit/qmarkdowntextedit.pc.in b/client/qmarkdowntextedit/qmarkdowntextedit.pc.in new file mode 100644 index 0000000..b616d65 --- /dev/null +++ b/client/qmarkdowntextedit/qmarkdowntextedit.pc.in @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/ + +Name: @PROJECT_NAME@ +Description: @PROJECT_DESCRIPTION@ +Version: @PROJECT_VERSION@ + +Requires: +Libs: -L${libdir} -lqmarkdowntextedit +Cflags: -I${includedir} diff --git a/client/qmarkdowntextedit/qmarkdowntextedit.pro b/client/qmarkdowntextedit/qmarkdowntextedit.pro index 518ae85..929c719 100644 --- a/client/qmarkdowntextedit/qmarkdowntextedit.pro +++ b/client/qmarkdowntextedit/qmarkdowntextedit.pro @@ -1,23 +1,5 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-01-11T16:56:21 -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = QMarkdownTextedit -TEMPLATE = app -TRANSLATIONS = trans/qmarkdowntextedit_de.ts -CONFIG += c++11 - -SOURCES += main.cpp \ - mainwindow.cpp \ - -HEADERS += mainwindow.h - -FORMS += mainwindow.ui - -include(qmarkdowntextedit.pri) +TEMPLATE = subdirs +SUBDIRS = app lib +app.file = qmarkdowntextedit-app.pro +lib.file = qmarkdowntextedit-lib.pro +app.depends = lib diff --git a/client/qmarkdowntextedit/qownlanguagedata.cpp b/client/qmarkdowntextedit/qownlanguagedata.cpp new file mode 100644 index 0000000..6b80615 --- /dev/null +++ b/client/qmarkdowntextedit/qownlanguagedata.cpp @@ -0,0 +1,7303 @@ +/* + * MIT License + * + * Copyright (c) 2019-2021 Waqar Ahmed -- + * + * 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 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 "qownlanguagedata.h" + +#include +#include +/* ------------------------ + * TEMPLATE FOR LANG DATA + * ------------------------- + * + * loadXXXData, where XXX is the language + * keywords are the language keywords e.g, const + * types are built-in types i.e, int, char, var + * literals are words like, true false + * builtin are the library functions + * other can contain any other thing, for e.g, in cpp it contains the + preprocessor + + xxx_keywords = { + }; + + xxx_types = { + }; + + xxx_literals = { + }; + + xxx_builtin = { + }; + + xxx_other = { + }; + +*/ + +/**********************************************************/ +/* C/C++ Data *********************************************/ +/**********************************************************/ + +static bool cppDataInitialized = false; +static QMultiHash cpp_keywords; +static QMultiHash cpp_types; +static QMultiHash cpp_builtin; +static QMultiHash cpp_literals; +static QMultiHash cpp_other; +void initCppData() { + cpp_keywords = QMultiHash{ + {('a'), QLatin1String("alignas")}, + {('a'), QLatin1String("alignof")}, + {('a'), QLatin1String("and")}, + {('a'), QLatin1String("and_eq")}, + {('a'), QLatin1String("asm")}, + {('b'), QLatin1String("bit_and")}, + {('b'), QLatin1String("bit_or")}, + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("case")}, + {('c'), QLatin1String("catch")}, + {('c'), QLatin1String("compl")}, + {('c'), QLatin1String("concept")}, + {('c'), QLatin1String("const")}, + {('c'), QLatin1String("constinit")}, + {('c'), QLatin1String("constexpr")}, + {('c'), QLatin1String("consteval")}, + {('c'), QLatin1String("const_cast")}, + {('c'), QLatin1String("continue")}, + {('c'), QLatin1String("co_await")}, + {('c'), QLatin1String("co_return")}, + {('c'), QLatin1String("co_yield")}, + {('d'), QLatin1String("decltype")}, + {('d'), QLatin1String("default")}, + {('d'), QLatin1String("delete")}, + {('d'), QLatin1String("do")}, + {('d'), QLatin1String("dynamic_cast")}, + {('e'), QLatin1String("else")}, + {('e'), QLatin1String("explicit")}, + {('e'), QLatin1String("export")}, + {('e'), QLatin1String("extern")}, + {('f'), QLatin1String("for")}, + {('f'), QLatin1String("friend")}, + {('g'), QLatin1String("goto")}, + {('i'), QLatin1String("if")}, + {('i'), QLatin1String("inline")}, + {('m'), QLatin1String("mutable")}, + {('n'), QLatin1String("new")}, + {('n'), QLatin1String("not")}, + {('n'), QLatin1String("not_eq")}, + {('n'), QLatin1String("noexcept")}, + {('o'), QLatin1String("or")}, + {('o'), QLatin1String("or_eq")}, + {('o'), QLatin1String("operator")}, + {('p'), QLatin1String("private")}, + {('p'), QLatin1String("protected")}, + {('p'), QLatin1String("public")}, + {('r'), QLatin1String("register")}, + {('r'), QLatin1String("reinterpret_cast")}, + {('r'), QLatin1String("requires")}, + {('r'), QLatin1String("return")}, + {('s'), QLatin1String("signal")}, + {('s'), QLatin1String("sizeof")}, + {('s'), QLatin1String("slot")}, + {('s'), QLatin1String("static")}, + {('s'), QLatin1String("static_assert")}, + {('s'), QLatin1String("static_cast")}, + {('s'), QLatin1String("switch")}, + {('t'), QLatin1String("template")}, + {('t'), QLatin1String("this")}, + {('t'), QLatin1String("thread_local")}, + {('t'), QLatin1String("throw")}, + {('t'), QLatin1String("try")}, + {('t'), QLatin1String("typeid")}, + {('t'), QLatin1String("typedef")}, + {('t'), QLatin1String("typename")}, + {('u'), QLatin1String("using")}, + {('v'), QLatin1String("volatile")}, + {('w'), QLatin1String("while")}, + {('x'), QLatin1String("xor")}, + {('x'), QLatin1String("xor_eq")}}; + + cpp_types = {{('a'), QLatin1String("auto")}, + {('b'), QLatin1String("bool")}, + {('c'), QLatin1String("char")}, + {('c'), QLatin1String("char8_t")}, + {('c'), QLatin1String("char16_t")}, + {('c'), QLatin1String("char32_t")}, + {('c'), QLatin1String("class")}, + {('d'), QLatin1String("double")}, + {('e'), QLatin1String("enum")}, + {('f'), QLatin1String("float")}, + {('i'), QLatin1String("int")}, + {('i'), QLatin1String("int8_t")}, + {('i'), QLatin1String("int16_t")}, + {('i'), QLatin1String("int32_t")}, + {('i'), QLatin1String("int64_t")}, + {('i'), QLatin1String("int_fast8_t")}, + {('i'), QLatin1String("int_fast16_t")}, + {('i'), QLatin1String("int_fast32_t")}, + {('i'), QLatin1String("int_fast64_t")}, + {('i'), QLatin1String("intmax_t")}, + {('i'), QLatin1String("intptr_t")}, + {('l'), QLatin1String("long")}, + {('n'), QLatin1String("namespace")}, + {('Q'), QLatin1String("QHash")}, + {('Q'), QLatin1String("QList")}, + {('Q'), QLatin1String("QMap")}, + {('Q'), QLatin1String("QString")}, + {('Q'), QLatin1String("QVector")}, + {('s'), QLatin1String("short")}, + {('s'), QLatin1String("size_t")}, + {('s'), QLatin1String("signed")}, + {('s'), QLatin1String("struct")}, + {('s'), QLatin1String("ssize_t")}, + {('u'), QLatin1String("uint8_t")}, + {('u'), QLatin1String("uint16_t")}, + {('u'), QLatin1String("uint32_t")}, + {('u'), QLatin1String("uint64_t")}, + {('u'), QLatin1String("uint_fast8_t")}, + {('u'), QLatin1String("uint_fast16_t")}, + {('u'), QLatin1String("uint_fast32_t")}, + {('u'), QLatin1String("uint_fast64_t")}, + {('u'), QLatin1String("uint_least8_t")}, + {('u'), QLatin1String("uint_least16_t")}, + {('u'), QLatin1String("uint_least32_t")}, + {('u'), QLatin1String("uint_least64_t")}, + {('u'), QLatin1String("uintmax_t")}, + {('u'), QLatin1String("uintptr_t")}, + {('u'), QLatin1String("unsigned")}, + {('u'), QLatin1String("union")}, + {('v'), QLatin1String("void")}, + {('w'), QLatin1String("wchar_t")}}; + + cpp_literals = {{('f'), QLatin1String("false")}, + {('n'), QLatin1String("nullptr")}, + {('N'), QLatin1String("NULL")}, + {('t'), QLatin1String("true")}}; + + cpp_builtin = {{('s'), QLatin1String("std")}, + {('s'), QLatin1String("string")}, + {('s'), QLatin1String("string_view")}, + {('w'), QLatin1String("wstring")}, + {('c'), QLatin1String("cin")}, + {('c'), QLatin1String("cout")}, + {('c'), QLatin1String("cerr")}, + {('c'), QLatin1String("clog")}, + {('s'), QLatin1String("stdin")}, + {('s'), QLatin1String("stdout")}, + {('s'), QLatin1String("stderr")}, + {('s'), QLatin1String("stringstream")}, + {('i'), QLatin1String("istringstream")}, + {('o'), QLatin1String("ostringstream")}, + {('a'), QLatin1String("auto_ptr")}, + {('d'), QLatin1String("deque")}, + {('l'), QLatin1String("list")}, + {('q'), QLatin1String("queue")}, + {('s'), QLatin1String("stack")}, + {('v'), QLatin1String("vector")}, + {('m'), QLatin1String("map")}, + {('s'), QLatin1String("set")}, + {('b'), QLatin1String("bitset")}, + {('m'), QLatin1String("multiset")}, + {('m'), QLatin1String("multimap")}, + {('u'), QLatin1String("unordered_set")}, + {('u'), QLatin1String("unordered_map")}, + {('u'), QLatin1String("unordered_multiset")}, + {('u'), QLatin1String("unordered_multimap")}, + {('a'), QLatin1String("array")}, + {('s'), QLatin1String("shared_ptr")}, + {('a'), QLatin1String("abort")}, + {('t'), QLatin1String("terminate")}, + {('a'), QLatin1String("abs")}, + {('a'), QLatin1String("acos")}, + {('a'), QLatin1String("asin")}, + {('a'), QLatin1String("atan2")}, + {('a'), QLatin1String("atan")}, + {('c'), QLatin1String("calloc")}, + {('c'), QLatin1String("ceil")}, + {('c'), QLatin1String("cosh")}, + {('c'), QLatin1String("cos")}, + {('e'), QLatin1String("exit")}, + {('e'), QLatin1String("exp")}, + {('f'), QLatin1String("fabs")}, + {('f'), QLatin1String("floor")}, + {('f'), QLatin1String("fmod")}, + {('f'), QLatin1String("fprintf")}, + {('f'), QLatin1String("fputs")}, + {('f'), QLatin1String("free")}, + {('f'), QLatin1String("frexp")}, + {('f'), QLatin1String("fscanf")}, + {('f'), QLatin1String("future")}, + {('i'), QLatin1String("isalnum")}, + {('i'), QLatin1String("isalpha")}, + {('i'), QLatin1String("iscntrl")}, + {('i'), QLatin1String("isdigit")}, + {('i'), QLatin1String("isgraph")}, + {('i'), QLatin1String("islower")}, + {('i'), QLatin1String("isprint")}, + {('i'), QLatin1String("ispunct")}, + {('i'), QLatin1String("isspace")}, + {('i'), QLatin1String("isupper")}, + {('i'), QLatin1String("isxdigit")}, + {('t'), QLatin1String("tolower")}, + {('t'), QLatin1String("toupper")}, + {('l'), QLatin1String("labs")}, + {('l'), QLatin1String("ldexp")}, + {('l'), QLatin1String("log10")}, + {('l'), QLatin1String("log")}, + {('m'), QLatin1String("malloc")}, + {('r'), QLatin1String("realloc")}, + {('m'), QLatin1String("main")}, + {('m'), QLatin1String("memchr")}, + {('m'), QLatin1String("memcmp")}, + {('m'), QLatin1String("memcpy")}, + {('m'), QLatin1String("memset")}, + {('m'), QLatin1String("modf")}, + {('p'), QLatin1String("pow")}, + {('p'), QLatin1String("printf")}, + {('p'), QLatin1String("putchar")}, + {('p'), QLatin1String("puts")}, + {('s'), QLatin1String("scanf")}, + {('s'), QLatin1String("sinh")}, + {('s'), QLatin1String("sin")}, + {('s'), QLatin1String("snprintf")}, + {('s'), QLatin1String("sprintf")}, + {('s'), QLatin1String("sqrt")}, + {('s'), QLatin1String("sscanf")}, + {('s'), QLatin1String("strcat")}, + {('s'), QLatin1String("strchr")}, + {('s'), QLatin1String("strcmp")}, + {('s'), QLatin1String("strcpy")}, + {('s'), QLatin1String("strcspn")}, + {('s'), QLatin1String("strlen")}, + {('s'), QLatin1String("strncat")}, + {('s'), QLatin1String("strncmp")}, + {('s'), QLatin1String("strncpy")}, + {('s'), QLatin1String("strpbrk")}, + {('s'), QLatin1String("strrchr")}, + {('s'), QLatin1String("strspn")}, + {('s'), QLatin1String("strstr")}, + {('t'), QLatin1String("tanh")}, + {('t'), QLatin1String("tan")}, + {('v'), QLatin1String("vfprintf")}, + {('v'), QLatin1String("vprintf")}, + {('v'), QLatin1String("vsprintf")}, + {('e'), QLatin1String("endl")}, + {('i'), QLatin1String("initializer_list")}, + {('u'), QLatin1String("unique_ptr")}, + {('c'), QLatin1String("complex")}, + {('i'), QLatin1String("imaginary")}}; + + cpp_other = { + {('d'), QLatin1String("define")}, {('e'), QLatin1String("else")}, + {('e'), QLatin1String("elif")}, {('e'), QLatin1String("endif")}, + {('e'), QLatin1String("error")}, {('i'), QLatin1String("if")}, + {('i'), QLatin1String("ifdef")}, {('i'), QLatin1String("ifndef")}, + {('i'), QLatin1String("include")}, {('l'), QLatin1String("line")}, + {('p'), QLatin1String("pragma")}, {('P'), QLatin1String("_Pragma")}, + {('u'), QLatin1String("undef")}, {('w'), QLatin1String("warning")}}; +} +void loadCppData(QMultiHash &typess, + QMultiHash &keywordss, + QMultiHash &builtins, + QMultiHash &literalss, + QMultiHash &others) { + if (!cppDataInitialized) { + initCppData(); + cppDataInitialized = true; + } + + typess = cpp_types; + keywordss = cpp_keywords; + builtins = cpp_builtin; + literalss = cpp_literals; + others = cpp_other; +} + +/**********************************************************/ +/* Shell Data *********************************************/ +/**********************************************************/ + +static bool shellDataInitialized = false; +static QMultiHash shell_keywords; +static QMultiHash shell_types; +static QMultiHash shell_literals; +static QMultiHash shell_builtin; +static QMultiHash shell_other; +void initShellData() { + shell_keywords = { + {('i'), QLatin1String("if")}, {('t'), QLatin1String("then")}, + {('e'), QLatin1String("else")}, {('e'), QLatin1String("elif")}, + {('f'), QLatin1String("fi")}, {('f'), QLatin1String("for")}, + {('w'), QLatin1String("while")}, {('i'), QLatin1String("in")}, + {('d'), QLatin1String("do")}, {('d'), QLatin1String("done")}, + {('c'), QLatin1String("case")}, {('e'), QLatin1String("esac")}, + {('f'), QLatin1String("function")}}; + + shell_types = {}; + + shell_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}}; + + shell_builtin = {{('b'), QLatin1String("break")}, + {('c'), QLatin1String("cd")}, + {('c'), QLatin1String("continue")}, + {('e'), QLatin1String("eval")}, + {('e'), QLatin1String("exec")}, + {('e'), QLatin1String("exit")}, + {('e'), QLatin1String("export")}, + {('g'), QLatin1String("getopts")}, + {('h'), QLatin1String("hash")}, + {('p'), QLatin1String("pwd")}, + {('r'), QLatin1String("readonly")}, + {('r'), QLatin1String("return")}, + {('s'), QLatin1String("shift")}, + {('t'), QLatin1String("test")}, + {('t'), QLatin1String("timestrap")}, + {('u'), QLatin1String("umask")}, + {('u'), QLatin1String("unset")}, + {('B'), QLatin1String("Bash")}, + {('a'), QLatin1String("alias")}, + {('b'), QLatin1String("bind")}, + {('b'), QLatin1String("builtin")}, + {('c'), QLatin1String("caller")}, + {('c'), QLatin1String("command")}, + {('d'), QLatin1String("declare")}, + {('e'), QLatin1String("echo")}, + {('e'), QLatin1String("enable")}, + {('h'), QLatin1String("help")}, + {('l'), QLatin1String("let")}, + {('l'), QLatin1String("local")}, + {('l'), QLatin1String("logout")}, + {('m'), QLatin1String("mapfile")}, + {('p'), QLatin1String("printfread")}, + {('r'), QLatin1String("readarray")}, + {('s'), QLatin1String("source")}, + {('t'), QLatin1String("type")}, + {('t'), QLatin1String("typeset")}, + {('u'), QLatin1String("ulimit")}, + {('u'), QLatin1String("unalias")}, + {('m'), QLatin1String("modifiers")}, + {('s'), QLatin1String("set")}, + {('s'), QLatin1String("shopt")}, + {('a'), QLatin1String("autoload")}, + {('b'), QLatin1String("bg")}, + {('b'), QLatin1String("bindkey")}, + {('b'), QLatin1String("bye")}, + {('c'), QLatin1String("cap")}, + {('c'), QLatin1String("chdir")}, + {('c'), QLatin1String("clone")}, + {('c'), QLatin1String("comparguments")}, + {('c'), QLatin1String("compcall")}, + {('c'), QLatin1String("compctl")}, + {('c'), QLatin1String("compdescribe")}, + {('c'), QLatin1String("compfilescompgroups")}, + {('c'), QLatin1String("compquote")}, + {('c'), QLatin1String("comptags")}, + {('c'), QLatin1String("comptry")}, + {('c'), QLatin1String("compvalues")}, + {('d'), QLatin1String("dirs")}, + {('d'), QLatin1String("disable")}, + {('d'), QLatin1String("disown")}, + {('e'), QLatin1String("echotc")}, + {('e'), QLatin1String("echoti")}, + {('e'), QLatin1String("emulatefc")}, + {('f'), QLatin1String("fg")}, + {('f'), QLatin1String("float")}, + {('f'), QLatin1String("functions")}, + {('g'), QLatin1String("getcap")}, + {('g'), QLatin1String("getln")}, + {('h'), QLatin1String("history")}, + {('i'), QLatin1String("integer")}, + {('j'), QLatin1String("jobs")}, + {('k'), QLatin1String("kill")}, + {('l'), QLatin1String("limit")}, + {('l'), QLatin1String("log")}, + {('n'), QLatin1String("noglob")}, + {('p'), QLatin1String("popd")}, + {('p'), QLatin1String("printpushd")}, + {('p'), QLatin1String("pushln")}, + {('r'), QLatin1String("rehash")}, + {('s'), QLatin1String("sched")}, + {('s'), QLatin1String("setcap")}, + {('s'), QLatin1String("setopt")}, + {('s'), QLatin1String("stat")}, + {('s'), QLatin1String("suspend")}, + {('t'), QLatin1String("ttyctl")}, + {('u'), QLatin1String("unfunction")}, + {('u'), QLatin1String("unhash")}, + {('u'), QLatin1String("unlimitunsetopt")}, + {('v'), QLatin1String("vared")}, + {('w'), QLatin1String("wait")}, + {('w'), QLatin1String("whence")}, + {('w'), QLatin1String("where")}, + {('w'), QLatin1String("which")}, + {('z'), QLatin1String("zcompile")}, + {('z'), QLatin1String("zformat")}, + {('z'), QLatin1String("zftp")}, + {('z'), QLatin1String("zle")}, + {('z'), QLatin1String("zmodload")}, + {('z'), QLatin1String("zparseopts")}, + {('z'), QLatin1String("zprof")}, + {('z'), QLatin1String("zpty")}, + {('z'), QLatin1String("zregexparse")}, + {('z'), QLatin1String("zsocket")}, + {('z'), QLatin1String("zstyle")}, + {('z'), QLatin1String("ztcp")}, + {('g'), QLatin1String("git")}, + {('r'), QLatin1String("rm")}, + {('s'), QLatin1String("sudo")}, + {('f'), QLatin1String("fdisk")}, + {('a'), QLatin1String("apt")}, + {('s'), QLatin1String("snap")}, + {('f'), QLatin1String("flatpak")}, + {('s'), QLatin1String("snapcraft")}, + {('y'), QLatin1String("yaourt")}, + {('n'), QLatin1String("nmcli")}, + {('p'), QLatin1String("pacman")}, + {('p'), QLatin1String("pamac")}, + {('f'), QLatin1String("fsck")}, + {('m'), QLatin1String("mount")}, + {('m'), QLatin1String("mkdir")}, + {('m'), QLatin1String("mkswap")}, + {('s'), QLatin1String("sleep")}, + {('l'), QLatin1String("ls")}, + {('w'), QLatin1String("wget")}, + {('k'), QLatin1String("kill")}, + {('k'), QLatin1String("killall")}, + {('g'), QLatin1String("gdb")}, + {('Q'), QLatin1String("QOwnNotes")}, + {('q'), QLatin1String("qownnotes")}, + {('d'), QLatin1String("docker")}, + {('o'), QLatin1String("openssl")}, + {('p'), QLatin1String("php")}, + {('p'), QLatin1String("python")}, + {('p'), QLatin1String("perl")}, + {('g'), QLatin1String("go")}, + {('c'), QLatin1String("curl")}}; + + shell_other = {}; +} + +void loadShellData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!shellDataInitialized) { + initShellData(); + shellDataInitialized = true; + } + types = shell_types; + keywords = shell_keywords; + builtin = shell_builtin; + literals = shell_literals; + other = shell_other; +} + +/**********************************************************/ +/* JS Data *********************************************/ +/**********************************************************/ +static bool JSDataInitialized = false; +static QMultiHash js_keywords; +static QMultiHash js_types; +static QMultiHash js_literals; +static QMultiHash js_builtin; +static QMultiHash js_other; +void initJSData() { + js_keywords = {{('i'), QLatin1String("in")}, + {('o'), QLatin1String("of")}, + {('i'), QLatin1String("if")}, + {('f'), QLatin1String("for")}, + {('w'), QLatin1String("while")}, + {('f'), QLatin1String("finally")}, + {('n'), QLatin1String("new")}, + {('f'), QLatin1String("function")}, + {('d'), QLatin1String("do")}, + {('r'), QLatin1String("return")}, + {('v'), QLatin1String("void")}, + {('e'), QLatin1String("else")}, + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("catch")}, + {('i'), QLatin1String("instanceof")}, + {('w'), QLatin1String("with")}, + {('t'), QLatin1String("throw")}, + {('c'), QLatin1String("case")}, + {('d'), QLatin1String("default")}, + {('t'), QLatin1String("try")}, + {('t'), QLatin1String("this")}, + {('s'), QLatin1String("switch")}, + {('c'), QLatin1String("continue")}, + {('t'), QLatin1String("typeof")}, + {('d'), QLatin1String("delete")}, + {('l'), QLatin1String("let")}, + {('y'), QLatin1String("yield")}, + {('c'), QLatin1String("const")}, + {('e'), QLatin1String("export")}, + {('s'), QLatin1String("super")}, + {('d'), QLatin1String("debugger")}, + {('a'), QLatin1String("as")}, + {('a'), QLatin1String("async")}, + {('a'), QLatin1String("await")}, + {('s'), QLatin1String("static")}, + {('i'), QLatin1String("import")}, + {('f'), QLatin1String("from")}, + {('a'), QLatin1String("as")}}; + + js_types = { + {('v'), QLatin1String("var")}, {('c'), QLatin1String("class")}, + {('b'), QLatin1String("byte")}, {('e'), QLatin1String("enum")}, + {('f'), QLatin1String("float")}, {('s'), QLatin1String("short")}, + {('l'), QLatin1String("long")}, {('i'), QLatin1String("int")}, + {('v'), QLatin1String("void")}, {('b'), QLatin1String("boolean")}, + {('d'), QLatin1String("double")}}; + + js_literals = { + {('f'), QLatin1String("false")}, {('n'), QLatin1String("null")}, + {('t'), QLatin1String("true")}, {('u'), QLatin1String("undefined")}, + {('N'), QLatin1String("NaN")}, {('I'), QLatin1String("Infinity")}}; + + js_builtin = {{('e'), QLatin1String("eval")}, + {('i'), QLatin1String("isFinite")}, + {('i'), QLatin1String("isNaN")}, + {('p'), QLatin1String("parseFloat")}, + {('p'), QLatin1String("parseInt")}, + {('d'), QLatin1String("decodeURI")}, + {('d'), QLatin1String("decodeURIComponent")}, + {('e'), QLatin1String("encodeURI")}, + {('e'), QLatin1String("encodeURIComponent")}, + {('e'), QLatin1String("escape")}, + {('u'), QLatin1String("unescape")}, + {('O'), QLatin1String("Object")}, + {('F'), QLatin1String("Function")}, + {('B'), QLatin1String("Boolean")}, + {('E'), QLatin1String("Error")}, + {('E'), QLatin1String("EvalError")}, + {('I'), QLatin1String("InternalError")}, + {('R'), QLatin1String("RangeError")}, + {('R'), QLatin1String("ReferenceError")}, + {('S'), QLatin1String("StopIteration")}, + {('S'), QLatin1String("SyntaxError")}, + {('T'), QLatin1String("TypeError")}, + {('U'), QLatin1String("URIError")}, + {('N'), QLatin1String("Number")}, + {('M'), QLatin1String("Math")}, + {('D'), QLatin1String("Date")}, + {('S'), QLatin1String("String")}, + {('R'), QLatin1String("RegExp")}, + {('A'), QLatin1String("Array")}, + {('F'), QLatin1String("Float32Array")}, + {('F'), QLatin1String("Float64Array")}, + {('I'), QLatin1String("Int16Array")}, + {('I'), QLatin1String("Int32Array")}, + {('I'), QLatin1String("Int8Array")}, + {('U'), QLatin1String("Uint16Array")}, + {('U'), QLatin1String("Uint32Array")}, + {('U'), QLatin1String("Uint8Array")}, + {('U'), QLatin1String("Uint8ClampedArray")}, + {('A'), QLatin1String("ArrayBuffer")}, + {('D'), QLatin1String("DataView")}, + {('J'), QLatin1String("JSON")}, + {('I'), QLatin1String("Intl")}, + {('a'), QLatin1String("arguments")}, + {('r'), QLatin1String("require")}, + {('m'), QLatin1String("module")}, + {('c'), QLatin1String("console")}, + {('w'), QLatin1String("window")}, + {('d'), QLatin1String("document")}, + {('S'), QLatin1String("Symbol")}, + {('S'), QLatin1String("Set")}, + {('M'), QLatin1String("Map")}, + {('W'), QLatin1String("WeakSet")}, + {('W'), QLatin1String("WeakMap")}, + {('P'), QLatin1String("Proxy")}, + {('R'), QLatin1String("Reflect")}, + {('P'), QLatin1String("Promise")}}; + + js_other = {}; +} + +void loadJSData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!JSDataInitialized) { + initJSData(); + JSDataInitialized = true; + } + types = js_types; + keywords = js_keywords; + builtin = js_builtin; + literals = js_literals; + other = js_other; +} + +/**********************************************************/ +/* Nix Data ***********************************************/ +/**********************************************************/ +static bool NixDataInitialized = false; +static QMultiHash nix_keywords; +static QMultiHash nix_types; +static QMultiHash nix_literals; +static QMultiHash nix_builtin; +static QMultiHash nix_other; + +// also see +// https://github.com/KDE/syntax-highlighting/blob/master/data/syntax/nix.xml +void initNixData() { + nix_keywords = { + {('i'), QLatin1String("in")}, {('a'), QLatin1String("assert")}, + {('k'), QLatin1String("keywords")}, {('r'), QLatin1String("rec")}, + {('a'), QLatin1String("and")}, {('o'), QLatin1String("or")}, + {('o'), QLatin1String("of")}, {('i'), QLatin1String("if")}, + {('f'), QLatin1String("for")}, {('w'), QLatin1String("while")}, + {('d'), QLatin1String("do")}, {('r'), QLatin1String("return")}, + {('e'), QLatin1String("else")}, {('b'), QLatin1String("break")}, + {('w'), QLatin1String("with")}, {('c'), QLatin1String("case")}, + {('c'), QLatin1String("continue")}, {('d'), QLatin1String("delete")}, + {('l'), QLatin1String("let")}, {('e'), QLatin1String("export")}, + {('a'), QLatin1String("as")}, {('i'), QLatin1String("import")}, + {('f'), QLatin1String("from")}, {('a'), QLatin1String("as")}}; + + nix_types = {}; + + nix_literals = { + {('f'), QLatin1String("false")}, {('n'), QLatin1String("null")}, + {('t'), QLatin1String("true")}, {('u'), QLatin1String("undefined")}, + {('N'), QLatin1String("NaN")}, {('I'), QLatin1String("Infinity")}}; + + nix_builtin = {{('a'), QLatin1String("abort")}, + {('b'), QLatin1String("baseNameOf")}, + {('d'), QLatin1String("derivation")}, + {('d'), QLatin1String("dirOf")}, + {('f'), QLatin1String("fetchTarball")}, + {('f'), QLatin1String("fetchFromGitHub")}, + {('i'), QLatin1String("import")}, + {('i'), QLatin1String("isNull")}, + {('m'), QLatin1String("map")}, + {('r'), QLatin1String("removeAttrs")}, + {('t'), QLatin1String("throw")}, + {('t'), QLatin1String("toString")}}; + + nix_other = { + {('b'), QLatin1String("builtins")}, + {('c'), QLatin1String("config")}, + {('p'), QLatin1String("pkgs")}, + {('i'), QLatin1String("inputs")}, + {('x'), QLatin1String("xdg")}, + {('e'), QLatin1String("environment")}, + }; +} + +void loadNixData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!NixDataInitialized) { + initNixData(); + NixDataInitialized = true; + } + types = nix_types; + keywords = nix_keywords; + builtin = nix_builtin; + literals = nix_literals; + other = nix_other; +} + +/**********************************************************/ +/* PHP Data *********************************************/ +/**********************************************************/ +static bool PHPDataInitialized = false; +static QMultiHash php_keywords; +static QMultiHash php_types; +static QMultiHash php_literals; +static QMultiHash php_builtin; +static QMultiHash php_other; +void initPHPData() { + php_keywords = {{('a'), QLatin1String("and")}, + {('l'), QLatin1String("list")}, + {('a'), QLatin1String("abstract")}, + {('g'), QLatin1String("global")}, + {('p'), QLatin1String("private")}, + {('e'), QLatin1String("echo")}, + {('i'), QLatin1String("interface")}, + {('a'), QLatin1String("as")}, + {('s'), QLatin1String("static")}, + {('e'), QLatin1String("endswitch")}, + {('i'), QLatin1String("if")}, + {('e'), QLatin1String("endwhile")}, + {('o'), QLatin1String("or")}, + {('c'), QLatin1String("const")}, + {('f'), QLatin1String("for")}, + {('e'), QLatin1String("endforeach")}, + {('s'), QLatin1String("self")}, + {('w'), QLatin1String("while")}, + {('i'), QLatin1String("isset")}, + {('p'), QLatin1String("public")}, + {('p'), QLatin1String("protected")}, + {('e'), QLatin1String("exit")}, + {('f'), QLatin1String("foreach")}, + {('t'), QLatin1String("throw")}, + {('e'), QLatin1String("elseif")}, + {('e'), QLatin1String("empty")}, + {('d'), QLatin1String("do")}, + {('x'), QLatin1String("xor")}, + {('r'), QLatin1String("return")}, + {('p'), QLatin1String("parent")}, + {('c'), QLatin1String("clone")}, + {('u'), QLatin1String("use")}, + {('e'), QLatin1String("else")}, + {('b'), QLatin1String("break")}, + {('p'), QLatin1String("print")}, + {('e'), QLatin1String("eval")}, + {('n'), QLatin1String("new")}, + {('c'), QLatin1String("catch")}, + {('c'), QLatin1String("case")}, + {('e'), QLatin1String("exception")}, + {('d'), QLatin1String("default")}, + {('d'), QLatin1String("die")}, + {('e'), QLatin1String("enddeclare")}, + {('f'), QLatin1String("final")}, + {('t'), QLatin1String("try")}, + {('s'), QLatin1String("switch")}, + {('c'), QLatin1String("continue")}, + {('e'), QLatin1String("endfor")}, + {('e'), QLatin1String("endif")}, + {('d'), QLatin1String("declare")}, + {('u'), QLatin1String("unset")}, + {('t'), QLatin1String("trait")}, + {('g'), QLatin1String("goto")}, + {('i'), QLatin1String("instanceof")}, + {('i'), QLatin1String("insteadof")}, + {('y'), QLatin1String("yield")}, + {('f'), QLatin1String("finally")}}; + + php_types = {{('v'), QLatin1String("var")}, + {('c'), QLatin1String("class")}, + {('e'), QLatin1String("enum")}, + {('a'), QLatin1String("array")}}; + + php_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('n'), QLatin1String("null")}}; + + php_builtin = { + + }; + + php_other = {{('i'), QLatin1String("include_once")}, + {('i'), QLatin1String("include")}, + {('_'), QLatin1String("__FILE__")}, + {('r'), QLatin1String("require")}, + {('r'), QLatin1String("require_once")}, + {('_'), QLatin1String("__CLASS__")}, + {('_'), QLatin1String("__LINE__")}, + {('_'), QLatin1String("__METHOD__")}, + {('_'), QLatin1String("__FUNCTION__")}, + {('_'), QLatin1String("__DIR__")}, + {('_'), QLatin1String("__NAMESPACE__")}, + + {('S'), QLatin1String("SERVER")}, + {('G'), QLatin1String("GET")}, + {('P'), QLatin1String("POST")}, + {('F'), QLatin1String("FILES")}, + {('R'), QLatin1String("REQUEST")}, + {('S'), QLatin1String("SESSION")}, + {('E'), QLatin1String("ENV")}, + {('C'), QLatin1String("COOKIE")}, + {('G'), QLatin1String("GLOBALS")}, + {('H'), QLatin1String("HTTP_RAW_POST_DATA")}, + {('a'), QLatin1String("argc")}, + {('a'), QLatin1String("argv")}, + {('p'), QLatin1String("php_errormsg")}, + {('h'), QLatin1String("http_response_header")}}; +} +void loadPHPData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!PHPDataInitialized) { + initPHPData(); + PHPDataInitialized = true; + } + types = php_types; + keywords = php_keywords; + builtin = php_builtin; + literals = php_literals; + other = php_other; +} + +/**********************************************************/ +/* QML Data *********************************************/ +/**********************************************************/ +static bool QMLDataInitialized = false; +static QMultiHash qml_keywords; +static QMultiHash qml_types; +static QMultiHash qml_literals; +static QMultiHash qml_builtin; +static QMultiHash qml_other; + +void initQMLData() { + qml_keywords = {{('d'), QLatin1String("default")}, + {('p'), QLatin1String("property")}, + {('i'), QLatin1String("int")}, + {('v'), QLatin1String("var")}, + {('s'), QLatin1String("string")}, + {('f'), QLatin1String("function")}, + {('r'), QLatin1String("readonly")}, + {('M'), QLatin1String("MouseArea")}, + {('d'), QLatin1String("delegate")}, + {('i'), QLatin1String("if")}, + {('e'), QLatin1String("else")}, + + {('e'), QLatin1String("eval")}, + {('i'), QLatin1String("isFinite")}, + {('i'), QLatin1String("isNaN")}, + {('p'), QLatin1String("parseFloat")}, + {('p'), QLatin1String("parseInt")}, + {('d'), QLatin1String("decodeURI")}, + {('d'), QLatin1String("decodeURIComponent")}, + {('e'), QLatin1String("encodeURI")}, + {('e'), QLatin1String("encodeURIComponent")}, + {('e'), QLatin1String("escape")}, + {('u'), QLatin1String("unescape")}, + {('O'), QLatin1String("Object")}, + {('E'), QLatin1String("Error")}, + {('E'), QLatin1String("EvalError")}, + {('I'), QLatin1String("InternalError")}, + {('R'), QLatin1String("RangeError")}, + {('R'), QLatin1String("ReferenceError")}, + {('S'), QLatin1String("StopIteration")}, + {('S'), QLatin1String("SyntaxError")}, + {('T'), QLatin1String("TypeError")}, + {('U'), QLatin1String("URIError")}, + {('N'), QLatin1String("Number")}, + {('M'), QLatin1String("Math")}, + {('D'), QLatin1String("Date")}, + {('S'), QLatin1String("String")}, + {('R'), QLatin1String("RegExp")}, + {('A'), QLatin1String("Array")}, + {('F'), QLatin1String("Float32Array")}, + {('F'), QLatin1String("Float64Array")}, + {('I'), QLatin1String("Int16Array")}, + {('I'), QLatin1String("Int32Array")}, + {('I'), QLatin1String("Int8Array")}, + {('U'), QLatin1String("Uint16Array")}, + {('U'), QLatin1String("Uint32Array")}, + {('U'), QLatin1String("Uint8Array")}, + {('U'), QLatin1String("Uint8ClampedArray")}, + {('A'), QLatin1String("ArrayBuffer")}, + {('D'), QLatin1String("DataView")}, + {('J'), QLatin1String("JSON")}, + {('I'), QLatin1String("Intl")}, + {('a'), QLatin1String("arguments")}, + {('m'), QLatin1String("module")}, + {('c'), QLatin1String("console")}, + {('w'), QLatin1String("window")}, + {('d'), QLatin1String("document")}, + {('S'), QLatin1String("Symbol")}, + {('S'), QLatin1String("Set")}, + {('M'), QLatin1String("Map")}, + {('W'), QLatin1String("WeakSet")}, + {('W'), QLatin1String("WeakMap")}, + {('P'), QLatin1String("Proxy")}, + {('R'), QLatin1String("Reflect")}, + {('B'), QLatin1String("Behavior")}, + {('c'), QLatin1String("color")}, + {('c'), QLatin1String("coordinate")}, + {('d'), QLatin1String("date")}, + {('e'), QLatin1String("enumeration")}, + {('f'), QLatin1String("font")}, + {('g'), QLatin1String("geocircle")}, + {('g'), QLatin1String("georectangle")}, + {('g'), QLatin1String("geoshape")}, + {('l'), QLatin1String("list")}, + {('m'), QLatin1String("matrix4x4")}, + {('p'), QLatin1String("parent")}, + {('p'), QLatin1String("point")}, + {('q'), QLatin1String("quaternion")}, + {('r'), QLatin1String("real")}, + {('s'), QLatin1String("size")}, + {('s'), QLatin1String("string")}, + {('v'), QLatin1String("variant")}, + {('v'), QLatin1String("vector2d")}, + {('v'), QLatin1String("vector3d")}, + {('v'), QLatin1String("vector4d")}, + {('P'), QLatin1String("Promise")}}; + + qml_types = { + {('R'), QLatin1String("Rectangle")}, + {('T'), QLatin1String("Text")}, + {('c'), QLatin1String("color")}, + {('I'), QLatin1String("Item")}, + {('u'), QLatin1String("url")}, + {('C'), QLatin1String("Component")}, + {('B'), QLatin1String("Button")}, + {('T'), QLatin1String("TextInput")}, + {('L'), QLatin1String("ListView")}, + + }; + + qml_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}}; + + qml_builtin = { + + }; + + qml_other = {{('i'), QLatin1String("import")}}; +} +void loadQMLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!QMLDataInitialized) { + initQMLData(); + QMLDataInitialized = true; + } + types = qml_types; + keywords = qml_keywords; + builtin = qml_builtin; + literals = qml_literals; + other = qml_other; +} + +/**********************************************************/ +/* Python Data *********************************************/ +/**********************************************************/ +static bool PyDataInitialized = false; +static QMultiHash py_keywords; +static QMultiHash py_types; +static QMultiHash py_literals; +static QMultiHash py_builtin; +static QMultiHash py_other; + +void initPyData() { + py_keywords = { + {('a'), QLatin1String("and")}, {('e'), QLatin1String("elif")}, + {('i'), QLatin1String("is")}, {('g'), QLatin1String("global")}, + {('a'), QLatin1String("as")}, {('i'), QLatin1String("in")}, + {('i'), QLatin1String("if")}, {('f'), QLatin1String("from")}, + {('r'), QLatin1String("raise")}, {('f'), QLatin1String("for")}, + {('e'), QLatin1String("except")}, {('f'), QLatin1String("finally")}, + {('p'), QLatin1String("print")}, {('p'), QLatin1String("pass")}, + {('r'), QLatin1String("return")}, {('e'), QLatin1String("exec")}, + {('e'), QLatin1String("else")}, {('b'), QLatin1String("break")}, + {('n'), QLatin1String("not")}, {('w'), QLatin1String("with")}, + {('c'), QLatin1String("class")}, {('a'), QLatin1String("assert")}, + {('y'), QLatin1String("yield")}, {('t'), QLatin1String("try")}, + {('w'), QLatin1String("while")}, {('c'), QLatin1String("continue")}, + {('d'), QLatin1String("del")}, {('o'), QLatin1String("or")}, + {('d'), QLatin1String("def")}, {('l'), QLatin1String("lambda")}, + {('a'), QLatin1String("async")}, {('a'), QLatin1String("await")}, + {('n'), QLatin1String("nonlocal")}, + }; + + py_types = { + + }; + + py_literals = {{('F'), QLatin1String("False")}, + {('T'), QLatin1String("True")}, + {('N'), QLatin1String("None")}}; + + py_builtin = {{('_'), QLatin1String("__import__")}, + {('a'), QLatin1String("abs")}, + {('a'), QLatin1String("all")}, + {('a'), QLatin1String("any")}, + {('a'), QLatin1String("apply")}, + {('a'), QLatin1String("ascii")}, + {('b'), QLatin1String("basestring")}, + {('b'), QLatin1String("bin")}, + {('b'), QLatin1String("bool")}, + {('b'), QLatin1String("buffer")}, + {('b'), QLatin1String("bytearray")}, + {('b'), QLatin1String("bytes")}, + {('c'), QLatin1String("callable")}, + {('c'), QLatin1String("chr")}, + {('c'), QLatin1String("classmethod")}, + {('c'), QLatin1String("cmp")}, + {('c'), QLatin1String("coerce")}, + {('c'), QLatin1String("compile")}, + {('c'), QLatin1String("complex")}, + {('d'), QLatin1String("delattr")}, + {('d'), QLatin1String("dict")}, + {('d'), QLatin1String("dir")}, + {('d'), QLatin1String("divmod")}, + {('e'), QLatin1String("enumerate")}, + {('e'), QLatin1String("eval")}, + {('e'), QLatin1String("execfile")}, + {('f'), QLatin1String("file")}, + {('f'), QLatin1String("filter")}, + {('f'), QLatin1String("float")}, + {('f'), QLatin1String("format")}, + {('f'), QLatin1String("frozenset")}, + {('g'), QLatin1String("getattr")}, + {('g'), QLatin1String("globals")}, + {('h'), QLatin1String("hasattr")}, + {('h'), QLatin1String("hash")}, + {('h'), QLatin1String("help")}, + {('h'), QLatin1String("hex")}, + {('i'), QLatin1String("id")}, + {('i'), QLatin1String("input")}, + {('i'), QLatin1String("int")}, + {('i'), QLatin1String("intern")}, + {('i'), QLatin1String("isinstance")}, + {('i'), QLatin1String("issubclass")}, + {('i'), QLatin1String("iter")}, + {('l'), QLatin1String("len")}, + {('l'), QLatin1String("list")}, + {('l'), QLatin1String("locals")}, + {('l'), QLatin1String("long")}, + {('m'), QLatin1String("map")}, + {('m'), QLatin1String("max")}, + {('m'), QLatin1String("memoryview")}, + {('m'), QLatin1String("min")}, + {('n'), QLatin1String("next")}, + {('o'), QLatin1String("object")}, + {('o'), QLatin1String("oct")}, + {('o'), QLatin1String("open")}, + {('o'), QLatin1String("ord")}, + {('p'), QLatin1String("pow")}, + {('p'), QLatin1String("property")}, + {('r'), QLatin1String("range")}, + {('r'), QLatin1String("raw_input")}, + {('r'), QLatin1String("reduce")}, + {('r'), QLatin1String("reload")}, + {('r'), QLatin1String("repr")}, + {('r'), QLatin1String("reversed")}, + {('r'), QLatin1String("round")}, + {('s'), QLatin1String("set")}, + {('s'), QLatin1String("setattr")}, + {('s'), QLatin1String("slice")}, + {('s'), QLatin1String("sorted")}, + {('s'), QLatin1String("staticmethod")}, + {('s'), QLatin1String("str")}, + {('s'), QLatin1String("sum")}, + {('s'), QLatin1String("super")}, + {('t'), QLatin1String("tuple")}, + {('t'), QLatin1String("type")}, + {('u'), QLatin1String("unichr")}, + {('u'), QLatin1String("unicode")}, + {('v'), QLatin1String("vars")}, + {('x'), QLatin1String("xrange")}, + {('z'), QLatin1String("zip")}}; + + py_other = {{('i'), QLatin1String("import")}}; +} +void loadPythonData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!PyDataInitialized) { + initPyData(); + PyDataInitialized = true; + } + types = py_types; + keywords = py_keywords; + builtin = py_builtin; + literals = py_literals; + other = py_other; +} + +/********************************************************/ +/*** Rust DATA ***********************************/ +/********************************************************/ +static bool rustDataInitialized = false; +static QMultiHash rust_keywords; +static QMultiHash rust_types; +static QMultiHash rust_literals; +static QMultiHash rust_builtin; +static QMultiHash rust_other; +void initRustData() { + rust_keywords = { + {('a'), QLatin1String("abstract")}, {('a'), QLatin1String("alignof")}, + {('a'), QLatin1String("as")}, {('a'), QLatin1String("async")}, + {('a'), QLatin1String("await")}, {('b'), QLatin1String("be")}, + {('b'), QLatin1String("box")}, {('b'), QLatin1String("break")}, + {('c'), QLatin1String("const")}, {('c'), QLatin1String("continue")}, + {('c'), QLatin1String("crate")}, {('d'), QLatin1String("do")}, + {('d'), QLatin1String("dyn")}, {('e'), QLatin1String("else")}, + {('e'), QLatin1String("extern")}, {('f'), QLatin1String("final")}, + {('f'), QLatin1String("fn")}, {('f'), QLatin1String("for")}, + {('i'), QLatin1String("if")}, {('i'), QLatin1String("impl")}, + {('i'), QLatin1String("in")}, {('l'), QLatin1String("let")}, + {('l'), QLatin1String("loop")}, {('m'), QLatin1String("match")}, + {('m'), QLatin1String("mod")}, {('m'), QLatin1String("move")}, + {('m'), QLatin1String("mut")}, {('o'), QLatin1String("offsetof")}, + {('o'), QLatin1String("once")}, {('o'), QLatin1String("override")}, + {('p'), QLatin1String("priv")}, {('p'), QLatin1String("pub")}, + {('p'), QLatin1String("pure")}, {('r'), QLatin1String("ref")}, + {('r'), QLatin1String("return")}, {('s'), QLatin1String("sizeof")}, + {('s'), QLatin1String("static")}, {('s'), QLatin1String("self")}, + {('S'), QLatin1String("Self")}, {('s'), QLatin1String("super")}, + {('t'), QLatin1String("trait")}, {('t'), QLatin1String("type")}, + {('t'), QLatin1String("typeof")}, {('u'), QLatin1String("unsafe")}, + {('u'), QLatin1String("unsized")}, {('u'), QLatin1String("use")}, + {('v'), QLatin1String("virtual")}, {('w'), QLatin1String("where")}, + {('w'), QLatin1String("while")}, {('y'), QLatin1String("yield")}, + }; + + rust_types = { + {('u'), QLatin1String("union")}, {('e'), QLatin1String("enum")}, + {('s'), QLatin1String("struct")}, + + {('i'), QLatin1String("i8")}, {('i'), QLatin1String("i16")}, + {('i'), QLatin1String("i32")}, {('i'), QLatin1String("i64")}, + {('i'), QLatin1String("i128")}, {('i'), QLatin1String("isize")}, + {('u'), QLatin1String("u8")}, {('u'), QLatin1String("u16")}, + {('u'), QLatin1String("u32")}, {('u'), QLatin1String("u64")}, + {('u'), QLatin1String("u128")}, {('u'), QLatin1String("usize")}, + {('f'), QLatin1String("f32")}, {('f'), QLatin1String("f64")}, + {('s'), QLatin1String("str")}, {('c'), QLatin1String("char")}, + {('b'), QLatin1String("bool")}, {('B'), QLatin1String("Box")}, + {('O'), QLatin1String("Option")}, {('R'), QLatin1String("Result")}, + {('S'), QLatin1String("String")}, {('V'), QLatin1String("Vec")}}; + + rust_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}}; + + rust_builtin = { + + }; + + rust_other = {{('a'), QLatin1String("assert!")}, + {('a'), QLatin1String("assert_eq!")}, + {('b'), QLatin1String("bitflags!")}, + {('b'), QLatin1String("bytes!")}, + {('c'), QLatin1String("cfg!")}, + {('c'), QLatin1String("col!")}, + {('c'), QLatin1String("concat!")}, + {('c'), QLatin1String("concat_idents!")}, + {('d'), QLatin1String("debug_assert!")}, + {('d'), QLatin1String("debug_assert_eq!")}, + {('e'), QLatin1String("env!")}, + {('p'), QLatin1String("panic!")}, + {('f'), QLatin1String("file!")}, + {('f'), QLatin1String("format!")}, + {('f'), QLatin1String("format_args!")}, + {('i'), QLatin1String("include_bin!")}, + {('i'), QLatin1String("include_str!")}, + {('l'), QLatin1String("line!")}, + {('l'), QLatin1String("local_data_key!")}, + {('m'), QLatin1String("module_path!")}, + {('o'), QLatin1String("option_env!")}, + {('p'), QLatin1String("print!")}, + {('p'), QLatin1String("println!")}, + {('s'), QLatin1String("select!")}, + {('s'), QLatin1String("stringify!")}, + {('t'), QLatin1String("try!")}, + {('u'), QLatin1String("unimplemented!")}, + {('u'), QLatin1String("unreachable!")}, + {('v'), QLatin1String("vec!")}, + {('w'), QLatin1String("write!")}, + {('w'), QLatin1String("writeln!")}, + {('m'), QLatin1String("macro_rules!")}, + {('a'), QLatin1String("assert_ne!")}, + {('d'), QLatin1String("debug_assert_ne!")}}; +} +void loadRustData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!rustDataInitialized) { + initRustData(); + rustDataInitialized = true; + } + types = rust_types; + keywords = rust_keywords; + builtin = rust_builtin; + literals = rust_literals; + other = rust_other; +} + +/********************************************************/ +/*** Java DATA ***********************************/ +/********************************************************/ +static bool javaDataInitialized = false; +static QMultiHash java_keywords; +static QMultiHash java_types; +static QMultiHash java_literals; +static QMultiHash java_builtin; +static QMultiHash java_other; +void initJavaData() { + java_keywords = {{('a'), QLatin1String("abstract")}, + {('a'), QLatin1String("assert")}, + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("case")}, + {('c'), QLatin1String("catch")}, + {('c'), QLatin1String("const")}, + {('c'), QLatin1String("continue")}, + {('d'), QLatin1String("default")}, + {('d'), QLatin1String("do")}, + {('e'), QLatin1String("else")}, + {('e'), QLatin1String("exports")}, + {('e'), QLatin1String("extends")}, + {('f'), QLatin1String("final")}, + {('f'), QLatin1String("finally")}, + {('f'), QLatin1String("for")}, + {('g'), QLatin1String("goto")}, + {('i'), QLatin1String("if")}, + {('i'), QLatin1String("implements")}, + {('i'), QLatin1String("import")}, + {('i'), QLatin1String("instanceof")}, + {('i'), QLatin1String("interface")}, + {('l'), QLatin1String("long")}, + {('m'), QLatin1String("module")}, + {('n'), QLatin1String("native")}, + {('n'), QLatin1String("new")}, + {('n'), QLatin1String("null")}, + {('o'), QLatin1String("open")}, + {('o'), QLatin1String("opens")}, + {('p'), QLatin1String("package")}, + {('p'), QLatin1String("private")}, + {('p'), QLatin1String("protected")}, + {('p'), QLatin1String("provides")}, + {('p'), QLatin1String("public")}, + {('r'), QLatin1String("requires")}, + {('r'), QLatin1String("return")}, + {('s'), QLatin1String("static")}, + {('s'), QLatin1String("strictfp")}, + {('s'), QLatin1String("super")}, + {('s'), QLatin1String("switch")}, + {('s'), QLatin1String("synchronized")}, + {('t'), QLatin1String("this")}, + {('t'), QLatin1String("throw")}, + {('t'), QLatin1String("throws")}, + {('t'), QLatin1String("to")}, + {('t'), QLatin1String("transient")}, + {('t'), QLatin1String("transitive")}, + {('t'), QLatin1String("try")}, + {('u'), QLatin1String("uses")}, + {('v'), QLatin1String("var")}, + {('v'), QLatin1String("volatile")}, + {('w'), QLatin1String("while")}, + {('w'), QLatin1String("with")}, + {('y'), QLatin1String("yield")}}; + + java_types = { + {('v'), QLatin1String("void")}, {('f'), QLatin1String("float")}, + {('b'), QLatin1String("boolean")}, {('b'), QLatin1String("byte")}, + {('i'), QLatin1String("int")}, {('c'), QLatin1String("char")}, + {('c'), QLatin1String("class")}, {('d'), QLatin1String("double")}, + {('e'), QLatin1String("enum")}, {('s'), QLatin1String("short")}, + + }; + + java_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}}; + + java_builtin = { + + }; + + java_other = { + + }; +} +void loadJavaData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!javaDataInitialized) { + initJavaData(); + javaDataInitialized = true; + } + types = java_types; + keywords = java_keywords; + builtin = java_builtin; + literals = java_literals; + other = java_other; +} + +/********************************************************/ +/*** C# DATA *************************************/ +/********************************************************/ +static bool csharpDataInitialized = false; +static QMultiHash csharp_keywords; +static QMultiHash csharp_types; +static QMultiHash csharp_literals; +static QMultiHash csharp_builtin; +static QMultiHash csharp_other; +void initCSharpData() { + csharp_keywords = {{('a'), QLatin1String("abstract")}, + {('a'), QLatin1String("add")}, + {('a'), QLatin1String("alias")}, + {('a'), QLatin1String("as")}, + {('a'), QLatin1String("ascending")}, + {('a'), QLatin1String("async")}, + {('a'), QLatin1String("await")}, + {('b'), QLatin1String("base")}, + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("case")}, + {('c'), QLatin1String("catch")}, + {('c'), QLatin1String("checked")}, + {('c'), QLatin1String("const")}, + {('c'), QLatin1String("continue")}, + {('d'), QLatin1String("decimal")}, + {('d'), QLatin1String("default")}, + {('d'), QLatin1String("delegate")}, + {('d'), QLatin1String("descending")}, + {('d'), QLatin1String("do")}, + {('d'), QLatin1String("dynamic")}, + {('e'), QLatin1String("else")}, + {('e'), QLatin1String("event")}, + {('e'), QLatin1String("explicit")}, + {('e'), QLatin1String("extern")}, + {('f'), QLatin1String("finally")}, + {('f'), QLatin1String("fixed")}, + {('f'), QLatin1String("for")}, + {('f'), QLatin1String("foreach")}, + {('f'), QLatin1String("from")}, + {('g'), QLatin1String("get")}, + {('g'), QLatin1String("global")}, + {('g'), QLatin1String("goto")}, + {('g'), QLatin1String("group")}, + {('i'), QLatin1String("if")}, + {('i'), QLatin1String("implicit")}, + {('i'), QLatin1String("in")}, + {('i'), QLatin1String("interface")}, + {('i'), QLatin1String("internal")}, + {('i'), QLatin1String("into")}, + {('i'), QLatin1String("is")}, + {('j'), QLatin1String("join")}, + {('l'), QLatin1String("let")}, + {('l'), QLatin1String("lock")}, + {('l'), QLatin1String("long")}, + {('n'), QLatin1String("namespace")}, + {('n'), QLatin1String("new")}, + {('o'), QLatin1String("object")}, + {('o'), QLatin1String("operator")}, + {('o'), QLatin1String("orderby")}, + {('o'), QLatin1String("out")}, + {('o'), QLatin1String("override")}, + {('p'), QLatin1String("params")}, + {('p'), QLatin1String("partial")}, + {('p'), QLatin1String("private")}, + {('p'), QLatin1String("protected")}, + {('p'), QLatin1String("public")}, + {('r'), QLatin1String("readonly")}, + {('r'), QLatin1String("ref")}, + {('r'), QLatin1String("remove")}, + {('r'), QLatin1String("return")}, + {('s'), QLatin1String("sealed")}, + {('s'), QLatin1String("select")}, + {('s'), QLatin1String("set")}, + {('s'), QLatin1String("sizeof")}, + {('s'), QLatin1String("stackalloc")}, + {('s'), QLatin1String("static")}, + {('s'), QLatin1String("switch")}, + {('t'), QLatin1String("this")}, + {('t'), QLatin1String("throw")}, + {('t'), QLatin1String("try")}, + {('t'), QLatin1String("typeof")}, + {('u'), QLatin1String("unchecked")}, + {('u'), QLatin1String("unsafe")}, + {('u'), QLatin1String("using")}, + {('v'), QLatin1String("value")}, + {('v'), QLatin1String("virtual")}, + {('v'), QLatin1String("volatile")}, + {('w'), QLatin1String("where")}, + {('w'), QLatin1String("while")}, + {('y'), QLatin1String("yield")}}; + + csharp_types = { + {('b'), QLatin1String("bool")}, {('b'), QLatin1String("byte")}, + {('c'), QLatin1String("char")}, {('c'), QLatin1String("class")}, + {('d'), QLatin1String("double")}, {('e'), QLatin1String("enum")}, + {('f'), QLatin1String("float")}, {('i'), QLatin1String("int")}, + {('s'), QLatin1String("sbyte")}, {('s'), QLatin1String("short")}, + {('s'), QLatin1String("string")}, {('s'), QLatin1String("struct")}, + {('u'), QLatin1String("uint")}, {('u'), QLatin1String("ulong")}, + {('u'), QLatin1String("ushort")}, {('v'), QLatin1String("var")}, + {('v'), QLatin1String("void")}, + }; + + csharp_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('n'), QLatin1String("null")}}; + + csharp_builtin = { + + }; + + csharp_other = { + {('d'), QLatin1String("define")}, {('e'), QLatin1String("elif")}, + {('e'), QLatin1String("else")}, {('e'), QLatin1String("endif")}, + {('e'), QLatin1String("endregion")}, {('e'), QLatin1String("error")}, + {('i'), QLatin1String("if")}, {('l'), QLatin1String("line")}, + {('p'), QLatin1String("pragma")}, {('r'), QLatin1String("region")}, + {('u'), QLatin1String("undef")}, {('w'), QLatin1String("warning")}}; +} +void loadCSharpData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!csharpDataInitialized) { + initCSharpData(); + csharpDataInitialized = true; + } + types = csharp_types; + keywords = csharp_keywords; + builtin = csharp_builtin; + literals = csharp_literals; + other = csharp_other; +} + +/********************************************************/ +/*** Go DATA *************************************/ +/********************************************************/ +static bool goDataInitialized = false; +static QMultiHash go_keywords; +static QMultiHash go_types; +static QMultiHash go_literals; +static QMultiHash go_builtin; +static QMultiHash go_other; +void initGoData() { + go_keywords = { + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("case")}, + {('c'), QLatin1String("chan")}, + {('c'), QLatin1String("const")}, + {('c'), QLatin1String("continue")}, + {('d'), QLatin1String("default")}, + {('d'), QLatin1String("defer")}, + {('e'), QLatin1String("else")}, + {('f'), QLatin1String("fallthrough")}, + {('f'), QLatin1String("for")}, + {('f'), QLatin1String("func")}, + {('g'), QLatin1String("go")}, + {('t'), QLatin1String("to")}, + {('i'), QLatin1String("if")}, + {('i'), QLatin1String("import")}, + {('i'), QLatin1String("interface")}, + {('p'), QLatin1String("package")}, + {('r'), QLatin1String("range")}, + {('r'), QLatin1String("return")}, + {('s'), QLatin1String("select")}, + {('s'), QLatin1String("struct")}, + {('s'), QLatin1String("switch")}, + {('t'), QLatin1String("type")}, + }; + + go_types = {{('m'), QLatin1String("map")}, + {('s'), QLatin1String("struct")}, + {('v'), QLatin1String("var")}, + {('b'), QLatin1String("bool")}, + {('b'), QLatin1String("byte")}, + {('c'), QLatin1String("complex64")}, + {('c'), QLatin1String("complex128")}, + {('f'), QLatin1String("float32")}, + {('f'), QLatin1String("float64")}, + {('i'), QLatin1String("int8")}, + {('i'), QLatin1String("int16")}, + {('i'), QLatin1String("int32")}, + {('i'), QLatin1String("int64")}, + {('s'), QLatin1String("string")}, + {('u'), QLatin1String("uint8")}, + {('u'), QLatin1String("uint16")}, + {('u'), QLatin1String("uint32")}, + {('u'), QLatin1String("uint64")}, + {('i'), QLatin1String("int")}, + {('u'), QLatin1String("uint")}, + {('u'), QLatin1String("uintptr")}, + {('r'), QLatin1String("rune")}}; + + go_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('n'), QLatin1String("nil")}, + {('i'), QLatin1String("iota")}}; + + go_builtin = { + {('a'), QLatin1String("append")}, {('c'), QLatin1String("cap")}, + {('c'), QLatin1String("close")}, {('c'), QLatin1String("complex")}, + {('c'), QLatin1String("copy")}, {('i'), QLatin1String("imag")}, + {('l'), QLatin1String("len")}, {('m'), QLatin1String("make")}, + {('n'), QLatin1String("new")}, {('p'), QLatin1String("panic")}, + {('p'), QLatin1String("print")}, {('p'), QLatin1String("println")}, + {('r'), QLatin1String("real")}, {('r'), QLatin1String("recover")}, + {('d'), QLatin1String("delete")}}; + + go_other = { + + }; +} +void loadGoData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!goDataInitialized) { + initGoData(); + goDataInitialized = true; + } + types = go_types; + keywords = go_keywords; + builtin = go_builtin; + literals = go_literals; + other = go_other; +} + +/********************************************************/ +/*** V DATA **************************************/ +/********************************************************/ +static bool vDataInitialized = false; +static QMultiHash v_keywords; +static QMultiHash v_types; +static QMultiHash v_literals; +static QMultiHash v_builtin; +static QMultiHash v_other; +void initVData() { + v_keywords = { + {('b'), QLatin1String("break")}, {('c'), QLatin1String("const")}, + {('c'), QLatin1String("continue")}, {('d'), QLatin1String("defer")}, + {('e'), QLatin1String("else")}, {('f'), QLatin1String("for")}, + {('f'), QLatin1String("fn")}, {('g'), QLatin1String("go")}, + {('g'), QLatin1String("goto")}, {('i'), QLatin1String("if")}, + {('i'), QLatin1String("import")}, {('i'), QLatin1String("interface")}, + {('r'), QLatin1String("return")}, {('s'), QLatin1String("struct")}, + {('s'), QLatin1String("switch")}, {('t'), QLatin1String("type")}, + {('p'), QLatin1String("pub")}, {('o'), QLatin1String("or")}, + {('n'), QLatin1String("none")}}; + + v_types = { + {('m'), QLatin1String("map")}, {('s'), QLatin1String("struct")}, + {('b'), QLatin1String("bool")}, {('b'), QLatin1String("byte")}, + {('f'), QLatin1String("f32")}, {('f'), QLatin1String("f64")}, + {('i'), QLatin1String("i8")}, {('i'), QLatin1String("i16")}, + {('i'), QLatin1String("int")}, {('i'), QLatin1String("i64")}, + {('i'), QLatin1String("i128")}, {('s'), QLatin1String("string")}, + {('u'), QLatin1String("u16")}, {('u'), QLatin1String("u32")}, + {('u'), QLatin1String("u64")}, {('u'), QLatin1String("u128")}, + {('u'), QLatin1String("byteptr")}, {('u'), QLatin1String("voidptr")}, + {('r'), QLatin1String("rune")}}; + + v_literals = { + {('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + }; + + v_builtin = {}; + + v_other = { + + }; +} +void loadVData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!vDataInitialized) { + initVData(); + vDataInitialized = true; + } + types = v_types; + keywords = v_keywords; + builtin = v_builtin; + literals = v_literals; + other = v_other; +} + +/********************************************************/ +/*** SQL DATA ************************************/ +/********************************************************/ +static bool sqlDataInitialized = false; +static QMultiHash sql_keywords; +static QMultiHash sql_types; +static QMultiHash sql_literals; +static QMultiHash sql_builtin; +static QMultiHash sql_other; +void initSQLData() { + sql_keywords = {{('A'), QLatin1String("ACTION")}, + {('A'), QLatin1String("ADD")}, + {('A'), QLatin1String("AFTER")}, + {('A'), QLatin1String("ALGORITHM")}, + {('A'), QLatin1String("ALL")}, + {('A'), QLatin1String("ALTER")}, + {('A'), QLatin1String("ANALYZE")}, + {('A'), QLatin1String("ANY")}, + {('A'), QLatin1String("APPLY")}, + {('A'), QLatin1String("AS")}, + {('A'), QLatin1String("ASC")}, + {('A'), QLatin1String("AUTHORIZATION")}, + {('A'), QLatin1String("AUTO_INCREMENT")}, + {('B'), QLatin1String("BACKUP")}, + {('B'), QLatin1String("BDB")}, + {('B'), QLatin1String("BEGIN")}, + {('B'), QLatin1String("BERKELEYDB")}, + {('B'), QLatin1String("BIGINT")}, + {('B'), QLatin1String("BINARY")}, + {('B'), QLatin1String("BIT")}, + {('B'), QLatin1String("BLOB")}, + {('B'), QLatin1String("BOOL")}, + {('B'), QLatin1String("BOOLEAN")}, + {('B'), QLatin1String("BREAK")}, + {('B'), QLatin1String("BROWSE")}, + {('B'), QLatin1String("BTREE")}, + {('B'), QLatin1String("BULK")}, + {('B'), QLatin1String("BY")}, + {('C'), QLatin1String("CALL")}, + {('C'), QLatin1String("CASCADED")}, + {('C'), QLatin1String("CASE")}, + {('C'), QLatin1String("CHAIN")}, + {('C'), QLatin1String("CHARACTER")}, + {('S'), QLatin1String("SET")}, + {('C'), QLatin1String("CHECKPOINT")}, + {('C'), QLatin1String("CLOSE")}, + {('C'), QLatin1String("CLUSTERED")}, + {('C'), QLatin1String("COALESCE")}, + {('C'), QLatin1String("COLLATE")}, + {('C'), QLatin1String("COLUMNS")}, + {('C'), QLatin1String("COMMENT")}, + {('C'), QLatin1String("COMMITTED")}, + {('C'), QLatin1String("COMPUTE")}, + {('C'), QLatin1String("CONNECT")}, + {('C'), QLatin1String("CONSISTENT")}, + {('C'), QLatin1String("CONSTRAINT")}, + {('C'), QLatin1String("CONTAINSTABLE")}, + {('C'), QLatin1String("CONTINUE")}, + {('C'), QLatin1String("CONVERT")}, + {('C'), QLatin1String("CREATE")}, + {('C'), QLatin1String("CROSS")}, + {('C'), QLatin1String("CURRENT_DATE")}, + {('_'), QLatin1String("_TIME")}, + {('_'), QLatin1String("_TIMESTAMP")}, + {('_'), QLatin1String("_USER")}, + {('C'), QLatin1String("CURSOR")}, + {('C'), QLatin1String("CYCLE")}, + {('D'), QLatin1String("DATABASES")}, + {('D'), QLatin1String("DATETIME")}, + {('D'), QLatin1String("DAY")}, + {('D'), QLatin1String("DBCC")}, + {('D'), QLatin1String("DEALLOCATE")}, + {('D'), QLatin1String("DEC")}, + {('D'), QLatin1String("DECIMAL")}, + {('D'), QLatin1String("DECLARE")}, + {('D'), QLatin1String("DEFAULT")}, + {('D'), QLatin1String("DEFINER")}, + {('D'), QLatin1String("DELAYED")}, + {('D'), QLatin1String("DELETE")}, + {('D'), QLatin1String("DELIMITERS")}, + {('D'), QLatin1String("DENY")}, + {('D'), QLatin1String("DESC")}, + {('D'), QLatin1String("DESCRIBE")}, + {('D'), QLatin1String("DETERMINISTIC")}, + {('D'), QLatin1String("DISABLE")}, + {('D'), QLatin1String("DISCARD")}, + {('D'), QLatin1String("DISK")}, + {('D'), QLatin1String("DISTINCT")}, + {('D'), QLatin1String("DISTINCTROW")}, + {('D'), QLatin1String("DISTRIBUTED")}, + {('D'), QLatin1String("DO")}, + {('D'), QLatin1String("DOUBLE")}, + {('D'), QLatin1String("DROP")}, + {('D'), QLatin1String("DUMMY")}, + {('D'), QLatin1String("DUMPFILE")}, + {('D'), QLatin1String("DUPLICATE")}, + {('E'), QLatin1String("ELSEIF")}, + {('E'), QLatin1String("ENABLE")}, + {('E'), QLatin1String("ENCLOSED")}, + {('E'), QLatin1String("END")}, + {('E'), QLatin1String("ENGINE")}, + {('E'), QLatin1String("ENUM")}, + {('E'), QLatin1String("ERRLVL")}, + {('E'), QLatin1String("ERRORS")}, + {('E'), QLatin1String("ESCAPED")}, + {('E'), QLatin1String("EXCEPT")}, + {('E'), QLatin1String("EXECUTE")}, + {('E'), QLatin1String("EXISTS")}, + {('E'), QLatin1String("EXIT")}, + {('E'), QLatin1String("EXPLAIN")}, + {('E'), QLatin1String("EXTENDED")}, + {('F'), QLatin1String("FETCH")}, + {('F'), QLatin1String("FIELDS")}, + {('F'), QLatin1String("FILE")}, + {('F'), QLatin1String("FILLFACTOR")}, + {('F'), QLatin1String("FIRST")}, + {('F'), QLatin1String("FIXED")}, + {('F'), QLatin1String("FLOAT")}, + {('F'), QLatin1String("FOLLOWING")}, + {('F'), QLatin1String("FOR")}, + {('E'), QLatin1String("EACH")}, + {('R'), QLatin1String("ROW")}, + {('F'), QLatin1String("FORCE")}, + {('F'), QLatin1String("FOREIGN")}, + {('F'), QLatin1String("FREETEXTTABLE")}, + {('F'), QLatin1String("FROM")}, + {('F'), QLatin1String("FULL")}, + {('F'), QLatin1String("FUNCTION")}, + {('G'), QLatin1String("GEOMETRYCOLLECTION")}, + {('G'), QLatin1String("GLOBAL")}, + {('G'), QLatin1String("GOTO")}, + {('G'), QLatin1String("GRANT")}, + {('G'), QLatin1String("GROUP")}, + {('H'), QLatin1String("HANDLER")}, + {('H'), QLatin1String("HASH")}, + {('H'), QLatin1String("HAVING")}, + {('H'), QLatin1String("HOLDLOCK")}, + {('H'), QLatin1String("HOUR")}, + {('I'), QLatin1String("IDENTITY_INSERT")}, + {('C'), QLatin1String("COL")}, + {('I'), QLatin1String("IF")}, + {('I'), QLatin1String("IGNORE")}, + {('I'), QLatin1String("IMPORT")}, + {('I'), QLatin1String("INDEX")}, + {('I'), QLatin1String("INFILE")}, + {('I'), QLatin1String("INNER")}, + {('I'), QLatin1String("INNODB")}, + {('I'), QLatin1String("INOUT")}, + {('I'), QLatin1String("INSERT")}, + {('I'), QLatin1String("INT")}, + {('I'), QLatin1String("INTEGER")}, + {('I'), QLatin1String("INTERSECT")}, + {('I'), QLatin1String("INTERVAL")}, + {('I'), QLatin1String("INTO")}, + {('I'), QLatin1String("INVOKER")}, + {('I'), QLatin1String("ISOLATION")}, + {('I'), QLatin1String("ITERATE")}, + {('J'), QLatin1String("JOIN")}, + {('K'), QLatin1String("KEYS")}, + {('K'), QLatin1String("KILL")}, + {('L'), QLatin1String("LANGUAGE")}, + {('L'), QLatin1String("LAST")}, + {('L'), QLatin1String("LEAVE")}, + {('L'), QLatin1String("LEFT")}, + {('L'), QLatin1String("LEVEL")}, + {('L'), QLatin1String("LIMIT")}, + {('L'), QLatin1String("LINENO")}, + {('L'), QLatin1String("LINES")}, + {('L'), QLatin1String("LINESTRING")}, + {('L'), QLatin1String("LOAD")}, + {('L'), QLatin1String("LOCAL")}, + {('L'), QLatin1String("LOCK")}, + {('L'), QLatin1String("LONGBLOB")}, + {('T'), QLatin1String("TEXT")}, + {('L'), QLatin1String("LOOP")}, + {('M'), QLatin1String("MATCHED")}, + {('M'), QLatin1String("MEDIUMBLOB")}, + {('I'), QLatin1String("INT")}, + {('T'), QLatin1String("TEXT")}, + {('M'), QLatin1String("MERGE")}, + {('M'), QLatin1String("MIDDLEINT")}, + {('M'), QLatin1String("MINUTE")}, + {('M'), QLatin1String("MODE")}, + {('M'), QLatin1String("MODIFIES")}, + {('M'), QLatin1String("MODIFY")}, + {('M'), QLatin1String("MONTH")}, + {('M'), QLatin1String("MULTILINESTRING")}, + {('P'), QLatin1String("POINT")}, + {('P'), QLatin1String("POLYGON")}, + {('N'), QLatin1String("NATIONAL")}, + {('N'), QLatin1String("NATURAL")}, + {('N'), QLatin1String("NCHAR")}, + {('N'), QLatin1String("NEXT")}, + {('N'), QLatin1String("NO")}, + {('N'), QLatin1String("NONCLUSTERED")}, + {('N'), QLatin1String("NULLIF")}, + {('N'), QLatin1String("NUMERIC")}, + {('O'), QLatin1String("OFF")}, + {('O'), QLatin1String("OFFSETS")}, + {('O'), QLatin1String("ON")}, + {('O'), QLatin1String("OPENDATASOURCE")}, + {('Q'), QLatin1String("QUERY")}, + {('R'), QLatin1String("ROWSET")}, + {('O'), QLatin1String("OPTIMIZE")}, + {('O'), QLatin1String("OPTIONALLY")}, + {('O'), QLatin1String("ORDER")}, + {('O'), QLatin1String("OUTER")}, + {('F'), QLatin1String("FILE")}, + {('O'), QLatin1String("OVER")}, + {('P'), QLatin1String("PARTIAL")}, + {('P'), QLatin1String("PARTITION")}, + {('P'), QLatin1String("PERCENT")}, + {('P'), QLatin1String("PIVOT")}, + {('P'), QLatin1String("PLAN")}, + {('P'), QLatin1String("POINT")}, + {('P'), QLatin1String("POLYGON")}, + {('P'), QLatin1String("PRECEDING")}, + {('P'), QLatin1String("PRECISION")}, + {('P'), QLatin1String("PREPARE")}, + {('P'), QLatin1String("PREV")}, + {('P'), QLatin1String("PRIMARY")}, + {('P'), QLatin1String("PRINT")}, + {('P'), QLatin1String("PRIVILEGES")}, + {('P'), QLatin1String("PROCEDURE")}, + {('P'), QLatin1String("PUBLIC")}, + {('P'), QLatin1String("PURGE")}, + {('Q'), QLatin1String("QUICK")}, + {('R'), QLatin1String("RAISERROR")}, + {('R'), QLatin1String("READS")}, + {('R'), QLatin1String("REAL")}, + {('R'), QLatin1String("RECONFIGURE")}, + {('R'), QLatin1String("REFERENCES")}, + {('R'), QLatin1String("RELEASE")}, + {('R'), QLatin1String("RENAME")}, + {('R'), QLatin1String("REPEATABLE")}, + {('R'), QLatin1String("REPLACE")}, + {('R'), QLatin1String("REPLICATION")}, + {('R'), QLatin1String("REQUIRE")}, + {('R'), QLatin1String("RESIGNAL")}, + {('R'), QLatin1String("RESTORE")}, + {('R'), QLatin1String("RESTRICT")}, + {('R'), QLatin1String("RETURNS")}, + {('R'), QLatin1String("REVOKE")}, + {('R'), QLatin1String("RIGHT")}, + {('R'), QLatin1String("ROLLBACK")}, + {('R'), QLatin1String("ROUTINE")}, + {('R'), QLatin1String("ROWCOUNT")}, + {('G'), QLatin1String("GUIDCOL")}, + {('R'), QLatin1String("RTREE")}, + {('R'), QLatin1String("RULE")}, + {('S'), QLatin1String("SAVEPOINT")}, + {('S'), QLatin1String("SCHEMA")}, + {('S'), QLatin1String("SECOND")}, + {('S'), QLatin1String("SELECT")}, + {('S'), QLatin1String("SERIALIZABLE")}, + {('S'), QLatin1String("SESSION_USER")}, + {('S'), QLatin1String("SETUSER")}, + {('S'), QLatin1String("SHARE")}, + {('S'), QLatin1String("SHOW")}, + {('S'), QLatin1String("SHUTDOWN")}, + {('S'), QLatin1String("SIMPLE")}, + {('S'), QLatin1String("SMALLINT")}, + {('S'), QLatin1String("SNAPSHOT")}, + {('S'), QLatin1String("SOME")}, + {('S'), QLatin1String("SONAME")}, + {('S'), QLatin1String("SQL")}, + {('S'), QLatin1String("STARTING")}, + {('S'), QLatin1String("STATISTICS")}, + {('S'), QLatin1String("STATUS")}, + {('S'), QLatin1String("STRIPED")}, + {('S'), QLatin1String("SYSTEM_USER")}, + {('T'), QLatin1String("TABLES")}, + {('T'), QLatin1String("TABLESPACE")}, + {('T'), QLatin1String("TEMPORARY")}, + {('T'), QLatin1String("TABLE")}, + {('T'), QLatin1String("TERMINATED")}, + {('T'), QLatin1String("TEXTSIZE")}, + {('T'), QLatin1String("THEN")}, + {('T'), QLatin1String("TIMESTAMP")}, + {('T'), QLatin1String("TINYBLOB")}, + {('I'), QLatin1String("INT")}, + {('T'), QLatin1String("TEXT")}, + {('T'), QLatin1String("TOP")}, + {('T'), QLatin1String("TRANSACTIONS")}, + {('T'), QLatin1String("TRIGGER")}, + {('T'), QLatin1String("TRUNCATE")}, + {('T'), QLatin1String("TSEQUAL")}, + {('T'), QLatin1String("TYPES")}, + {('U'), QLatin1String("UNBOUNDED")}, + {('U'), QLatin1String("UNCOMMITTED")}, + {('U'), QLatin1String("UNDEFINED")}, + {('U'), QLatin1String("UNION")}, + {('U'), QLatin1String("UNIQUE")}, + {('U'), QLatin1String("UNLOCK")}, + {('U'), QLatin1String("UNPIVOT")}, + {('U'), QLatin1String("UNSIGNED")}, + {('U'), QLatin1String("UPDATETEXT")}, + {('U'), QLatin1String("USAGE")}, + {('U'), QLatin1String("USE")}, + {('U'), QLatin1String("USER")}, + {('U'), QLatin1String("USING")}, + {('V'), QLatin1String("VALUES")}, + {('V'), QLatin1String("VARBINARY")}, + {('C'), QLatin1String("CHAR")}, + {('C'), QLatin1String("CHARACTER")}, + {('Y'), QLatin1String("YING")}, + {('V'), QLatin1String("VIEW")}, + {('W'), QLatin1String("WAITFOR")}, + {('W'), QLatin1String("WARNINGS")}, + {('W'), QLatin1String("WHEN")}, + {('W'), QLatin1String("WHERE")}, + {('W'), QLatin1String("WHILE")}, + {('W'), QLatin1String("WITH")}, + {('R'), QLatin1String("ROLLUP")}, + {('I'), QLatin1String("IN")}, + {('W'), QLatin1String("WORK")}, + {('W'), QLatin1String("WRITETEXT")}, + {('Y'), QLatin1String("YEAR")}}; + + sql_types = { + + }; + + sql_literals = { + {('A'), QLatin1String("TRUE")}, + {('F'), QLatin1String("FALSE")}, + {('N'), QLatin1String("NULL")}, + }; + + sql_builtin = { + {('A'), QLatin1String("AVG")}, {('C'), QLatin1String("COUNT")}, + {('F'), QLatin1String("FIRST")}, {('F'), QLatin1String("FORMAT")}, + {('L'), QLatin1String("LAST")}, {('L'), QLatin1String("LCASE")}, + {('L'), QLatin1String("LEN")}, {('M'), QLatin1String("MAX")}, + {('M'), QLatin1String("MID")}, {('M'), QLatin1String("MIN")}, + {('M'), QLatin1String("MOD")}, {('N'), QLatin1String("NOW")}, + {('R'), QLatin1String("ROUND")}, {('S'), QLatin1String("SUM")}, + {('U'), QLatin1String("UCASE")}}; + + sql_other = { + + }; +} +void loadSQLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!sqlDataInitialized) { + initSQLData(); + sqlDataInitialized = true; + } + types = sql_types; + keywords = sql_keywords; + builtin = sql_builtin; + literals = sql_literals; + other = sql_other; +} + +/********************************************************/ +/*** System Verilog DATA *************************/ +/********************************************************/ +static bool systemverilogDataInitialized = false; +static QMultiHash systemverilog_keywords; +static QMultiHash systemverilog_types; +static QMultiHash systemverilog_literals; +static QMultiHash systemverilog_builtin; +static QMultiHash systemverilog_other; +void initSystemVerilogData() { + systemverilog_keywords = { + {('a'), QLatin1String("and")}, + {('a'), QLatin1String("assign")}, + {('a'), QLatin1String("automatic")}, + {('c'), QLatin1String("cell")}, + {('c'), QLatin1String("cmos")}, + {('c'), QLatin1String("config")}, + {('d'), QLatin1String("deassign")}, + {('d'), QLatin1String("defparam")}, + {('d'), QLatin1String("define")}, + {('d'), QLatin1String("design")}, + {('d'), QLatin1String("disable")}, + {('e'), QLatin1String("edge")}, + {('e'), QLatin1String("endconfig")}, + {('e'), QLatin1String("endgenerate")}, + {('e'), QLatin1String("endprimitive")}, + {('e'), QLatin1String("endtable")}, + {('e'), QLatin1String("event")}, + {('f'), QLatin1String("force")}, + {('f'), QLatin1String("fork")}, + {('j'), QLatin1String("join")}, + {('j'), QLatin1String("join_any")}, + {('j'), QLatin1String("join_none")}, + {('f'), QLatin1String("forkjoin")}, + {('g'), QLatin1String("generate")}, + {('h'), QLatin1String("highz0")}, + {('h'), QLatin1String("highz1")}, + {('i'), QLatin1String("ifnone")}, + {('i'), QLatin1String("incdir")}, + {('i'), QLatin1String("include")}, + {('i'), QLatin1String("initial")}, + {('i'), QLatin1String("inout")}, + {('i'), QLatin1String("input")}, + {('i'), QLatin1String("instance")}, + {('l'), QLatin1String("large")}, + {('l'), QLatin1String("liblist")}, + {('l'), QLatin1String("library")}, + {('l'), QLatin1String("localparam")}, + {('m'), QLatin1String("macromodule")}, + {('m'), QLatin1String("medium")}, + {('n'), QLatin1String("nand")}, + {('n'), QLatin1String("negedge")}, + {('n'), QLatin1String("nmos")}, + {('n'), QLatin1String("nor")}, + {('n'), QLatin1String("noshowcancelled")}, + {('n'), QLatin1String("not")}, + {('n'), QLatin1String("notif0")}, + {('n'), QLatin1String("notif1")}, + {('o'), QLatin1String("or")}, + {('o'), QLatin1String("output")}, + {('p'), QLatin1String("parameter")}, + {('p'), QLatin1String("pmos")}, + {('p'), QLatin1String("posedge")}, + {('p'), QLatin1String("primitive")}, + {('p'), QLatin1String("pull0")}, + {('p'), QLatin1String("pull1")}, + {('p'), QLatin1String("pulldown")}, + {('p'), QLatin1String("pullup")}, + {('p'), QLatin1String("pulsestyle_onevent")}, + {('p'), QLatin1String("pulsestyle_ondetect")}, + {('r'), QLatin1String("rcmos")}, + {('r'), QLatin1String("resetall")}, + {('r'), QLatin1String("release")}, + {('r'), QLatin1String("rnmos")}, + {('r'), QLatin1String("rpmos")}, + {('r'), QLatin1String("rtran")}, + {('r'), QLatin1String("rtranif0")}, + {('r'), QLatin1String("rtranif1")}, + {('s'), QLatin1String("scalared")}, + {('s'), QLatin1String("showcancelled")}, + {('s'), QLatin1String("signed")}, + {('s'), QLatin1String("small")}, + {('s'), QLatin1String("specparam")}, + {('s'), QLatin1String("strong0")}, + {('s'), QLatin1String("strong1")}, + {('t'), QLatin1String("table")}, + {('t'), QLatin1String("tran")}, + {('t'), QLatin1String("tranif0")}, + {('t'), QLatin1String("tranif1")}, + {('u'), QLatin1String("undef")}, + {('u'), QLatin1String("undefineall")}, + {('u'), QLatin1String("unsigned")}, + {('u'), QLatin1String("use")}, + {('v'), QLatin1String("vectored")}, + {('w'), QLatin1String("wait")}, + {('w'), QLatin1String("weak0")}, + {('w'), QLatin1String("weak1")}, + {('m'), QLatin1String("mailbox")}, + {('c'), QLatin1String("checker")}, + {('e'), QLatin1String("endchecker")}, + {('v'), QLatin1String("virtual")}, + {('l'), QLatin1String("local")}, + {('c'), QLatin1String("const")}, + {('p'), QLatin1String("protected")}, + {('p'), QLatin1String("package")}, + {('e'), QLatin1String("endpackage")}, + {('r'), QLatin1String("rand")}, + {('r'), QLatin1String("randc")}, + {('c'), QLatin1String("constraint")}, + {('r'), QLatin1String("randomize")}, + {('w'), QLatin1String("with")}, + {('i'), QLatin1String("inside")}, + {('d'), QLatin1String("dist")}, + {('r'), QLatin1String("randcase")}, + {('r'), QLatin1String("randsequence")}, + {('g'), QLatin1String("get_randstate")}, + {('s'), QLatin1String("set_randstate")}, + {('s'), QLatin1String("srandom")}, + {('s'), QLatin1String("struct")}, + {('p'), QLatin1String("packed")}, + {('f'), QLatin1String("final")}, + {('i'), QLatin1String("import")}, + {('c'), QLatin1String("context")}, + {('p'), QLatin1String("pure")}, + {('v'), QLatin1String("void")}, + {('c'), QLatin1String("chandle")}, + {('m'), QLatin1String("modport")}, + {('c'), QLatin1String("cover")}, + {('c'), QLatin1String("coverpoint")}, + {('p'), QLatin1String("program")}, + {('e'), QLatin1String("endprogram")}, + {('b'), QLatin1String("bins")}, + {('b'), QLatin1String("binsof")}, + {('i'), QLatin1String("illegal_bins")}, + {('i'), QLatin1String("ignore_bins")}, + {('a'), QLatin1String("alias")}, + {('m'), QLatin1String("matches")}, + {('s'), QLatin1String("solve")}, + {('s'), QLatin1String("static")}, + {('a'), QLatin1String("assert")}, + {('a'), QLatin1String("assume")}, + {('b'), QLatin1String("before")}, + {('e'), QLatin1String("expect")}, + {('b'), QLatin1String("bind")}, + {('e'), QLatin1String("extends")}, + {('t'), QLatin1String("tagged")}, + {('e'), QLatin1String("extern")}, + {('f'), QLatin1String("first_match")}, + {('t'), QLatin1String("throughout")}, + {('t'), QLatin1String("timescale")}, + {('t'), QLatin1String("timeprecision")}, + {('t'), QLatin1String("timeunit")}, + {('p'), QLatin1String("priority")}, + {('t'), QLatin1String("type")}, + {('v'), QLatin1String("var")}, + {('c'), QLatin1String("cross")}, + {('r'), QLatin1String("ref")}, + {('w'), QLatin1String("wait_order")}, + {('i'), QLatin1String("intersect")}, + {('w'), QLatin1String("wildcard")}, + {('w'), QLatin1String("within")}, + {('t'), QLatin1String("triggered")}, + {('s'), QLatin1String("std")}, + {('a'), QLatin1String("accept_on")}, + {('e'), QLatin1String("eventually")}, + {('g'), QLatin1String("global")}, + {('i'), QLatin1String("implements")}, + {('i'), QLatin1String("implies")}, + {('i'), QLatin1String("interconnect")}, + {('l'), QLatin1String("let")}, + {('l'), QLatin1String("line")}, + {('n'), QLatin1String("nettype")}, + {('n'), QLatin1String("nexttime")}, + {('r'), QLatin1String("reject_on")}, + {('r'), QLatin1String("restrict")}, + {('s'), QLatin1String("soft")}, + {('s'), QLatin1String("s_always")}, + {('s'), QLatin1String("s_eventually")}, + {('s'), QLatin1String("s_nexttime")}, + {('s'), QLatin1String("s_until")}, + {('s'), QLatin1String("s_until_with")}, + {('s'), QLatin1String("strong")}, + {('s'), QLatin1String("sync_accept_on")}, + {('s'), QLatin1String("sync_reject_on")}, + {('u'), QLatin1String("unique")}, + {('u'), QLatin1String("unique0")}, + {('u'), QLatin1String("until")}, + {('u'), QLatin1String("until_with")}, + {('u'), QLatin1String("untyped")}, + {('w'), QLatin1String("weak")}, + {('s'), QLatin1String("start")}, + {('e'), QLatin1String("end")}, + {('i'), QLatin1String("iff")}, + {('i'), QLatin1String("if")}, + {('e'), QLatin1String("else")}, + {('c'), QLatin1String("case")}, + {('c'), QLatin1String("casex")}, + {('c'), QLatin1String("casez")}, + {('d'), QLatin1String("default")}, + {('d'), QLatin1String("default_nettype")}, + {('e'), QLatin1String("endcase")}, + {('f'), QLatin1String("forever")}, + {('r'), QLatin1String("repeat")}, + {('w'), QLatin1String("while")}, + {('f'), QLatin1String("for")}, + {('r'), QLatin1String("return")}, + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("continue")}, + {('d'), QLatin1String("do")}, + {('w'), QLatin1String("while")}, + {('f'), QLatin1String("foreach")}, + {('m'), QLatin1String("module")}, + {('e'), QLatin1String("endmodule")}, + {('f'), QLatin1String("function")}, + {('e'), QLatin1String("endfunction")}, + {('c'), QLatin1String("class")}, + {('e'), QLatin1String("endclass")}, + {('b'), QLatin1String("begin")}, + {('e'), QLatin1String("end")}, + }; + + systemverilog_types = { + {('w'), QLatin1String("wand")}, {('w'), QLatin1String("wor")}, + {('x'), QLatin1String("xnor")}, {('x'), QLatin1String("xor")}, + {('s'), QLatin1String("semaphore")}, {('s'), QLatin1String("supply0")}, + {('s'), QLatin1String("supply1")}, {('u'), QLatin1String("uwire")}, + {('t'), QLatin1String("tri")}, {('t'), QLatin1String("tri0")}, + {('t'), QLatin1String("tri1")}, {('t'), QLatin1String("triand")}, + {('t'), QLatin1String("trior")}, {('t'), QLatin1String("trireg")}, + {('g'), QLatin1String("genvar")}, {('b'), QLatin1String("buf")}, + {('b'), QLatin1String("bufif0")}, {('b'), QLatin1String("bufif1")}, + {('w'), QLatin1String("wire")}, {('r'), QLatin1String("reg")}, + {('l'), QLatin1String("logic")}, {('s'), QLatin1String("string")}, + {('b'), QLatin1String("bit")}, {('b'), QLatin1String("byte")}, + {('i'), QLatin1String("int")}, {('i'), QLatin1String("integer")}, + {('t'), QLatin1String("time")}, {('r'), QLatin1String("realtime")}, + {('l'), QLatin1String("longint")}, {('s'), QLatin1String("shortint")}, + {('s'), QLatin1String("shortreal")}, {('r'), QLatin1String("real")}, + {('e'), QLatin1String("enum")}, {('u'), QLatin1String("union")}, + {('s'), QLatin1String("struct")}, + }; + + systemverilog_literals = { + {('X'), QLatin1String("X")}, + {('Z'), QLatin1String("Z")}, + }; + + systemverilog_builtin = { + {('d'), QLatin1String("display")}, {('e'), QLatin1String("error")}, + {('w'), QLatin1String("warning")}, {('r'), QLatin1String("random")}, + {('u'), QLatin1String("urandom")}, {('f'), QLatin1String("finish")}, + {('p'), QLatin1String("print")}, {('m'), QLatin1String("monitor")}, + }; + + systemverilog_other = { + {('a'), QLatin1String("always")}, + {('a'), QLatin1String("always_comb")}, + {('a'), QLatin1String("always_ff")}, + {('a'), QLatin1String("always_latch")}, + {('a'), QLatin1String("always_latch")}, + }; +} +void loadSystemVerilogData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!systemverilogDataInitialized) { + initSystemVerilogData(); + systemverilogDataInitialized = true; + } + types = systemverilog_types; + keywords = systemverilog_keywords; + builtin = systemverilog_builtin; + literals = systemverilog_literals; + other = systemverilog_other; +} + +/********************************************************/ +/*** JSON DATA ***********************************/ +/********************************************************/ +static bool jsonDataInitialized = false; +static QMultiHash json_keywords; +static QMultiHash json_types; +static QMultiHash json_literals; +static QMultiHash json_builtin; +static QMultiHash json_other; +void initJSONData() { + json_keywords = {}; + + json_types = {}; + + json_literals = {{('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('n'), QLatin1String("null")}}; + + json_builtin = {}; + + json_other = {}; +} +void loadJSONData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!jsonDataInitialized) { + initJSONData(); + jsonDataInitialized = true; + } + types = json_types; + keywords = json_keywords; + builtin = json_builtin; + literals = json_literals; + other = json_other; +} + +/********************************************************/ +/*** CSS DATA ***********************************/ +/********************************************************/ +static bool cssDataInitialized = false; +static QMultiHash css_keywords; +static QMultiHash css_types; +static QMultiHash css_literals; +static QMultiHash css_builtin; +static QMultiHash css_other; +void initCSSData() { + css_keywords = {{'i', QLatin1String("important")}, + {'p', QLatin1String("px")}, + {'e', QLatin1String("em")}}; + + css_types = {{'a', QLatin1String("align")}, + {'c', QLatin1String("content")}, + {'i', QLatin1String("items")}, + {'s', QLatin1String("self")}, + {'a', QLatin1String("all")}, + {'a', QLatin1String("animation")}, + {'d', QLatin1String("delay")}, + {'d', QLatin1String("direction")}, + {'d', QLatin1String("duration")}, + {'f', QLatin1String("fill")}, + {'m', QLatin1String("mode")}, + {'i', QLatin1String("iteration")}, + {'c', QLatin1String("count")}, + {'n', QLatin1String("name")}, + {'p', QLatin1String("play")}, + {'s', QLatin1String("state")}, + {'t', QLatin1String("timing")}, + {'f', QLatin1String("function")}, + {'a', QLatin1String("azimuth")}, + {'b', QLatin1String("backface")}, + {'v', QLatin1String("visibility")}, + {'a', QLatin1String("attachment")}, + {'b', QLatin1String("blend")}, + {'m', QLatin1String("mode")}, + {'c', QLatin1String("clip")}, + {'c', QLatin1String("color")}, + {'i', QLatin1String("image")}, + {'o', QLatin1String("origin")}, + {'p', QLatin1String("position")}, + {'r', QLatin1String("repeat")}, + {'s', QLatin1String("size")}, + {'b', QLatin1String("background")}, + {'b', QLatin1String("bleed")}, + {'c', QLatin1String("color")}, + {'r', QLatin1String("radius")}, + {'r', QLatin1String("radius")}, + {'s', QLatin1String("style")}, + {'w', QLatin1String("width")}, + {'b', QLatin1String("bottom")}, + {'c', QLatin1String("collapse")}, + {'c', QLatin1String("color")}, + {'i', QLatin1String("image")}, + {'o', QLatin1String("outset")}, + {'r', QLatin1String("repeat")}, + {'s', QLatin1String("source")}, + {'s', QLatin1String("slice")}, + {'w', QLatin1String("width")}, + {'c', QLatin1String("color")}, + {'s', QLatin1String("style")}, + {'w', QLatin1String("width")}, + {'l', QLatin1String("left")}, + {'r', QLatin1String("radius")}, + {'c', QLatin1String("color")}, + {'s', QLatin1String("style")}, + {'w', QLatin1String("width")}, + {'r', QLatin1String("right")}, + {'s', QLatin1String("spacing")}, + {'s', QLatin1String("style")}, + {'c', QLatin1String("color")}, + {'l', QLatin1String("left")}, + {'r', QLatin1String("radius")}, + {'r', QLatin1String("radius")}, + {'s', QLatin1String("style")}, + {'w', QLatin1String("width")}, + {'t', QLatin1String("top")}, + {'w', QLatin1String("width")}, + {'b', QLatin1String("border")}, + {'b', QLatin1String("bottom")}, + {'b', QLatin1String("break")}, + {'b', QLatin1String("box")}, + {'s', QLatin1String("shadow")}, + {'b', QLatin1String("box")}, + {'s', QLatin1String("sizing")}, + {'a', QLatin1String("after")}, + {'b', QLatin1String("before")}, + {'b', QLatin1String("break")}, + {'i', QLatin1String("inside")}, + {'c', QLatin1String("caption")}, + {'s', QLatin1String("side")}, + {'c', QLatin1String("caret")}, + {'c', QLatin1String("color")}, + {'c', QLatin1String("clear")}, + {'c', QLatin1String("clip")}, + {'c', QLatin1String("color")}, + {'c', QLatin1String("columns")}, + {'c', QLatin1String("column")}, + {'c', QLatin1String("count")}, + {'f', QLatin1String("fill")}, + {'g', QLatin1String("gap")}, + {'r', QLatin1String("rule")}, + {'c', QLatin1String("color")}, + {'s', QLatin1String("style")}, + {'w', QLatin1String("width")}, + {'s', QLatin1String("span")}, + {'w', QLatin1String("width")}, + {'c', QLatin1String("content")}, + {'i', QLatin1String("increment")}, + {'c', QLatin1String("counter")}, + {'r', QLatin1String("reset")}, + {'a', QLatin1String("after")}, + {'b', QLatin1String("before")}, + {'c', QLatin1String("cue")}, + {'c', QLatin1String("cursor")}, + {'d', QLatin1String("direction")}, + {'d', QLatin1String("display")}, + {'e', QLatin1String("elevation")}, + {'e', QLatin1String("empty")}, + {'c', QLatin1String("cells")}, + {'f', QLatin1String("filter")}, + {'f', QLatin1String("flex")}, + {'b', QLatin1String("basis")}, + {'d', QLatin1String("direction")}, + {'f', QLatin1String("feature")}, + {'s', QLatin1String("settings")}, + {'f', QLatin1String("flex")}, + {'f', QLatin1String("flow")}, + {'g', QLatin1String("grow")}, + {'s', QLatin1String("shrink")}, + {'w', QLatin1String("wrap")}, + {'f', QLatin1String("float")}, + {'f', QLatin1String("family")}, + {'k', QLatin1String("kerning")}, + {'l', QLatin1String("language")}, + {'o', QLatin1String("override")}, + {'a', QLatin1String("adjust")}, + {'s', QLatin1String("size")}, + {'s', QLatin1String("stretch")}, + {'s', QLatin1String("style")}, + {'s', QLatin1String("synthesis")}, + {'v', QLatin1String("variant")}, + {'a', QLatin1String("alternates")}, + {'c', QLatin1String("caps")}, + {'e', QLatin1String("east")}, + {'a', QLatin1String("asian")}, + {'l', QLatin1String("ligatures")}, + {'n', QLatin1String("numeric")}, + {'p', QLatin1String("position")}, + {'w', QLatin1String("weight")}, + {'f', QLatin1String("font")}, + {'a', QLatin1String("area")}, + {'a', QLatin1String("auto")}, + {'c', QLatin1String("columns")}, + {'f', QLatin1String("flow")}, + {'r', QLatin1String("rows")}, + {'e', QLatin1String("end")}, + {'g', QLatin1String("gap")}, + {'s', QLatin1String("start")}, + {'c', QLatin1String("column")}, + {'g', QLatin1String("gap")}, + {'e', QLatin1String("end")}, + {'g', QLatin1String("gap")}, + {'s', QLatin1String("start")}, + {'r', QLatin1String("row")}, + {'a', QLatin1String("areas")}, + {'c', QLatin1String("columns")}, + {'r', QLatin1String("rows")}, + {'t', QLatin1String("template")}, + {'g', QLatin1String("grid")}, + {'h', QLatin1String("hanging")}, + {'p', QLatin1String("punctuation")}, + {'h', QLatin1String("height")}, + {'h', QLatin1String("hyphens")}, + {'i', QLatin1String("isolation")}, + {'j', QLatin1String("justify")}, + {'c', QLatin1String("content")}, + {'i', QLatin1String("items")}, + {'s', QLatin1String("self")}, + {'l', QLatin1String("leftimage")}, + {'l', QLatin1String("letter")}, + {'s', QLatin1String("spacing")}, + {'b', QLatin1String("break")}, + {'l', QLatin1String("line")}, + {'s', QLatin1String("style")}, + {'i', QLatin1String("image")}, + {'s', QLatin1String("style")}, + {'p', QLatin1String("position")}, + {'t', QLatin1String("type")}, + {'l', QLatin1String("list")}, + {'s', QLatin1String("style")}, + {'b', QLatin1String("bottom")}, + {'l', QLatin1String("left")}, + {'r', QLatin1String("right")}, + {'t', QLatin1String("top")}, + {'m', QLatin1String("margin")}, + {'m', QLatin1String("marker")}, + {'o', QLatin1String("offset")}, + {'m', QLatin1String("marks")}, + {'m', QLatin1String("max")}, + {'h', QLatin1String("height")}, + {'w', QLatin1String("width")}, + {'m', QLatin1String("min")}, + {'m', QLatin1String("mix")}, + {'b', QLatin1String("blend")}, + {'m', QLatin1String("mode")}, + {'n', QLatin1String("nav")}, + {'u', QLatin1String("up")}, + {'d', QLatin1String("down")}, + {'l', QLatin1String("left")}, + {'r', QLatin1String("right")}, + {'o', QLatin1String("opacity")}, + {'o', QLatin1String("order")}, + {'o', QLatin1String("orphans")}, + {'c', QLatin1String("color")}, + {'o', QLatin1String("offset")}, + {'s', QLatin1String("style")}, + {'w', QLatin1String("width")}, + {'o', QLatin1String("outline")}, + {'w', QLatin1String("wrap")}, + {'o', QLatin1String("overflow")}, + {'b', QLatin1String("bottom")}, + {'l', QLatin1String("left")}, + {'r', QLatin1String("right")}, + {'t', QLatin1String("top")}, + {'p', QLatin1String("padding")}, + {'b', QLatin1String("break")}, + {'a', QLatin1String("after")}, + {'b', QLatin1String("before")}, + {'i', QLatin1String("inside")}, + {'p', QLatin1String("page")}, + {'a', QLatin1String("after")}, + {'b', QLatin1String("before")}, + {'p', QLatin1String("pause")}, + {'p', QLatin1String("perspective")}, + {'o', QLatin1String("origin")}, + {'r', QLatin1String("range")}, + {'p', QLatin1String("pitch")}, + {'c', QLatin1String("content")}, + {'i', QLatin1String("items")}, + {'p', QLatin1String("place")}, + {'s', QLatin1String("self")}, + {'p', QLatin1String("play")}, + {'d', QLatin1String("during")}, + {'p', QLatin1String("position")}, + {'q', QLatin1String("quotes")}, + {'r', QLatin1String("resize")}, + {'r', QLatin1String("rest")}, + {'a', QLatin1String("after")}, + {'b', QLatin1String("before")}, + {'r', QLatin1String("rest")}, + {'r', QLatin1String("richness")}, + {'r', QLatin1String("right")}, + {'s', QLatin1String("size")}, + {'h', QLatin1String("header")}, + {'n', QLatin1String("numeral")}, + {'s', QLatin1String("speak")}, + {'p', QLatin1String("punctuation")}, + {'s', QLatin1String("speak")}, + {'s', QLatin1String("speech")}, + {'r', QLatin1String("rate")}, + {'s', QLatin1String("stress")}, + {'t', QLatin1String("tab")}, + {'s', QLatin1String("size")}, + {'t', QLatin1String("table")}, + {'l', QLatin1String("layout")}, + {'t', QLatin1String("text")}, + {'a', QLatin1String("align")}, + {'l', QLatin1String("last")}, + {'d', QLatin1String("decoration")}, + {'c', QLatin1String("color")}, + {'l', QLatin1String("line")}, + {'s', QLatin1String("skip")}, + {'s', QLatin1String("style")}, + {'i', QLatin1String("indent")}, + {'o', QLatin1String("overflow")}, + {'s', QLatin1String("shadow")}, + {'t', QLatin1String("transform")}, + {'u', QLatin1String("underline")}, + {'p', QLatin1String("position")}, + {'t', QLatin1String("top")}, + {'t', QLatin1String("transform")}, + {'o', QLatin1String("origin")}, + {'s', QLatin1String("style")}, + {'t', QLatin1String("transition")}, + {'d', QLatin1String("delay")}, + {'d', QLatin1String("duration")}, + {'p', QLatin1String("property")}, + {'t', QLatin1String("timing")}, + {'f', QLatin1String("function")}, + {'u', QLatin1String("unicode")}, + {'b', QLatin1String("bidi")}, + {'v', QLatin1String("vertical")}, + {'a', QLatin1String("align")}, + {'v', QLatin1String("visibility")}, + {'b', QLatin1String("balance")}, + {'d', QLatin1String("duration")}, + {'f', QLatin1String("family")}, + {'p', QLatin1String("pitch")}, + {'r', QLatin1String("range")}, + {'r', QLatin1String("rate")}, + {'s', QLatin1String("stress")}, + {'v', QLatin1String("volume")}, + {'v', QLatin1String("voice")}, + {'v', QLatin1String("volume")}, + {'w', QLatin1String("white")}, + {'s', QLatin1String("space")}, + {'w', QLatin1String("widows")}, + {'w', QLatin1String("width")}, + {'w', QLatin1String("will")}, + {'c', QLatin1String("change")}, + {'w', QLatin1String("word")}, + {'b', QLatin1String("break")}, + {'s', QLatin1String("spacing")}, + {'w', QLatin1String("wrap")}, + {'x', QLatin1String("x")}, + {'y', QLatin1String("y")}, + {'z', QLatin1String("z")}, + {'i', QLatin1String("index")}, + {'r', QLatin1String("rgb")}, + {'s', QLatin1String("sans")}, + {'s', QLatin1String("serif")}, + {'n', QLatin1String("normal")}}; + + css_literals = {}; + + css_builtin = {}; + + css_other = {}; +} +void loadCSSData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!cssDataInitialized) { + initCSSData(); + cssDataInitialized = true; + } + types = css_types; + keywords = css_keywords; + builtin = css_builtin; + literals = css_literals; + other = css_other; +} + +/********************************************************/ +/*** Typescript DATA *********************************/ +/********************************************************/ +static bool typescriptDataInitialized = false; +static QMultiHash typescript_keywords; +static QMultiHash typescript_types; +static QMultiHash typescript_literals; +static QMultiHash typescript_builtin; +static QMultiHash typescript_other; +void initTypescriptData() { + typescript_keywords = { + {'i', QLatin1String("in")}, {'i', QLatin1String("if")}, + {'f', QLatin1String("for")}, {'w', QLatin1String("while")}, + {'f', QLatin1String("finally")}, {'n', QLatin1String("new")}, + {'f', QLatin1String("function")}, {'d', QLatin1String("do")}, + {'r', QLatin1String("return")}, {'v', QLatin1String("void")}, + {'e', QLatin1String("else")}, {'b', QLatin1String("break")}, + {'c', QLatin1String("catch")}, {'i', QLatin1String("instanceof")}, + {'w', QLatin1String("with")}, {'t', QLatin1String("throw")}, + {'c', QLatin1String("case")}, {'d', QLatin1String("default")}, + {'t', QLatin1String("try")}, {'t', QLatin1String("this")}, + {'s', QLatin1String("switch")}, {'c', QLatin1String("continue")}, + {'t', QLatin1String("typeof")}, {'d', QLatin1String("delete")}, + {'l', QLatin1String("let")}, {'y', QLatin1String("yield")}, + {'c', QLatin1String("const")}, {'p', QLatin1String("public")}, + {'p', QLatin1String("private")}, {'p', QLatin1String("protected")}, + {'g', QLatin1String("get")}, {'s', QLatin1String("set")}, + {'s', QLatin1String("super")}, {'s', QLatin1String("static")}, + {'i', QLatin1String("implements")}, {'e', QLatin1String("export")}, + {'i', QLatin1String("import")}, {'d', QLatin1String("declare")}, + {'t', QLatin1String("type")}, {'n', QLatin1String("namespace")}, + {'a', QLatin1String("abstract")}, {'a', QLatin1String("as")}, + {'f', QLatin1String("from")}, {'e', QLatin1String("extends")}, + {'a', QLatin1String("async")}, {'a', QLatin1String("await")}}; + + typescript_types = {{'v', QLatin1String("var")}, + {'c', QLatin1String("class")}, + {'e', QLatin1String("enum")}}; + + typescript_literals = { + {('f'), QLatin1String("false")}, {('n'), QLatin1String("null")}, + {('t'), QLatin1String("true")}, {('u'), QLatin1String("undefined")}, + {('N'), QLatin1String("NaN")}, {('I'), QLatin1String("Infinity")}}; + + typescript_builtin = {{'e', QLatin1String("eval")}, + {'i', QLatin1String("isFinite")}, + {'i', QLatin1String("isNaN")}, + {'p', QLatin1String("parseFloat")}, + {'p', QLatin1String("parseInt")}, + {'d', QLatin1String("decodeURI")}, + {'d', QLatin1String("decodeURIComponent")}, + {'e', QLatin1String("encodeURI")}, + {'e', QLatin1String("encodeURIComponent")}, + {'e', QLatin1String("escape")}, + {'u', QLatin1String("unescape")}, + {'O', QLatin1String("Object")}, + {'F', QLatin1String("Function")}, + {'B', QLatin1String("Boolean")}, + {'E', QLatin1String("Error")}, + {'E', QLatin1String("EvalError")}, + {'I', QLatin1String("InternalError")}, + {'R', QLatin1String("RangeError")}, + {'R', QLatin1String("ReferenceError")}, + {'S', QLatin1String("StopIteration")}, + {'S', QLatin1String("SyntaxError")}, + {'T', QLatin1String("TypeError")}, + {'U', QLatin1String("URIError")}, + {'N', QLatin1String("Number")}, + {'M', QLatin1String("Math")}, + {'D', QLatin1String("Date")}, + {'S', QLatin1String("String")}, + {'R', QLatin1String("RegExp")}, + {'A', QLatin1String("Array")}, + {'F', QLatin1String("Float32Array")}, + {'F', QLatin1String("Float64Array")}, + {'I', QLatin1String("Int16Array")}, + {'I', QLatin1String("Int32Array")}, + {'I', QLatin1String("Int8Array")}, + {'U', QLatin1String("Uint16Array")}, + {'U', QLatin1String("Uint32Array")}, + {'U', QLatin1String("Uint8Array")}, + {'U', QLatin1String("Uint8ClampedArray")}, + {'A', QLatin1String("ArrayBuffer")}, + {'D', QLatin1String("DataView")}, + {'J', QLatin1String("JSON")}, + {'I', QLatin1String("Intl")}, + {'a', QLatin1String("arguments")}, + {'r', QLatin1String("require")}, + {'m', QLatin1String("module")}, + {'c', QLatin1String("console")}, + {'w', QLatin1String("window")}, + {'d', QLatin1String("document")}, + {'a', QLatin1String("any")}, + {'n', QLatin1String("number")}, + {'b', QLatin1String("boolean")}, + {'s', QLatin1String("string")}, + {'v', QLatin1String("void")}, + {'P', QLatin1String("Promise")}}; + + typescript_other = {}; +} +void loadTypescriptData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!typescriptDataInitialized) { + initTypescriptData(); + typescriptDataInitialized = true; + } + types = typescript_types; + keywords = typescript_keywords; + builtin = typescript_builtin; + literals = typescript_literals; + other = typescript_other; +} + +/********************************************************/ +/*** YAML DATA ***************************************/ +/********************************************************/ +static bool YAMLDataInitialized = false; +static QMultiHash YAML_keywords; +static QMultiHash YAML_types; +static QMultiHash YAML_literals; +static QMultiHash YAML_builtin; +static QMultiHash YAML_other; +void initYAMLData() { + YAML_keywords = {}; + YAML_types = {}; + YAML_literals = { + {('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('n'), QLatin1String("null")}, + }; + + YAML_builtin = {}; + YAML_other = {}; +} +void loadYAMLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!YAMLDataInitialized) { + initYAMLData(); + YAMLDataInitialized = true; + } + types = YAML_types; + keywords = YAML_keywords; + builtin = YAML_builtin; + literals = YAML_literals; + other = YAML_other; +} + +/********************************************************/ +/*** VEX DATA ***************************************/ +/********************************************************/ +static bool vexDataInitialized = false; +static QMultiHash vex_keywords; +static QMultiHash vex_types; +static QMultiHash vex_literals; +static QMultiHash vex_builtin; +static QMultiHash vex_other; +void initVEXData() { + vex_keywords = { + {'b', QLatin1String("break")}, {'c', QLatin1String("continue")}, + {'d', QLatin1String("do")}, {'e', QLatin1String("else")}, + {'f', QLatin1String("for")}, {'f', QLatin1String("foreach")}, + {'f', QLatin1String("forpoints")}, {'f', QLatin1String("function")}, + {'g', QLatin1String("gather")}, {'i', QLatin1String("if")}, + {'i', QLatin1String("illuminance")}, {'r', QLatin1String("return")}, + {'w', QLatin1String("while")}}; + vex_types = { + {'b', QLatin1String("bsdf")}, {'c', QLatin1String("char")}, + {'c', QLatin1String("color")}, {'f', QLatin1String("float")}, + {'i', QLatin1String("int")}, {'i', QLatin1String("integer")}, + {'m', QLatin1String("matrix")}, {'m', QLatin1String("matrix2")}, + {'m', QLatin1String("matrix3")}, {'m', QLatin1String("matrix4")}, + {'n', QLatin1String("normal")}, {'p', QLatin1String("point")}, + {'s', QLatin1String("string")}, {'s', QLatin1String("struct")}, + {'t', QLatin1String("typedef")}, {'u', QLatin1String("union")}, + {'v', QLatin1String("vector")}, {'v', QLatin1String("vector2")}, + {'v', QLatin1String("vector4")}, {'v', QLatin1String("void")}, + }; + vex_literals = { + {('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('n'), QLatin1String("null")}, + }; + + vex_builtin = {{'D', QLatin1String("Du")}, + {'D', QLatin1String("Dv")}, + {'D', QLatin1String("Dw")}, + {'a', QLatin1String("abs")}, + {'a', QLatin1String("accessframe")}, + {'a', QLatin1String("acos")}, + {'a', QLatin1String("addattrib")}, + {'a', QLatin1String("addattribute")}, + {'a', QLatin1String("adddetailattrib")}, + {'a', QLatin1String("addgroup")}, + {'a', QLatin1String("addpoint")}, + {'a', QLatin1String("addpointattrib")}, + {'a', QLatin1String("addprim")}, + {'a', QLatin1String("addprimattrib")}, + {'a', QLatin1String("addvariablename")}, + {'a', QLatin1String("addvertex")}, + {'a', QLatin1String("addvertexattrib")}, + {'a', QLatin1String("addvisualizer")}, + {'a', QLatin1String("agentaddclip")}, + {'a', QLatin1String("agentclipcatalog")}, + {'a', QLatin1String("agentclipchannel")}, + {'a', QLatin1String("agentcliplength")}, + {'a', QLatin1String("agentclipnames")}, + {'a', QLatin1String("agentclipsample")}, + {'a', QLatin1String("agentclipsamplelocal")}, + {'a', QLatin1String("agentclipsamplerate")}, + {'a', QLatin1String("agentclipsampleworld")}, + {'a', QLatin1String("agentcliptimes")}, + {'a', QLatin1String("agentclipweights")}, + {'a', QLatin1String("agentcollisionlayer")}, + {'a', QLatin1String("agentcurrentlayer")}, + {'a', QLatin1String("agentlayerbindings")}, + {'a', QLatin1String("agentlayers")}, + {'a', QLatin1String("agentlayershapes")}, + {'a', QLatin1String("agentlocaltransform")}, + {'a', QLatin1String("agentlocaltransforms")}, + {'a', QLatin1String("agentrigchildren")}, + {'a', QLatin1String("agentrigfind")}, + {'a', QLatin1String("agentrigparent")}, + {'a', QLatin1String("agenttransformcount")}, + {'a', QLatin1String("agenttransformnames")}, + {'a', QLatin1String("agenttransformtolocal")}, + {'a', QLatin1String("agenttransformtoworld")}, + {'a', QLatin1String("agentworldtransform")}, + {'a', QLatin1String("agentworldtransforms")}, + {'a', QLatin1String("albedo")}, + {'a', QLatin1String("alphaname")}, + {'a', QLatin1String("ambient")}, + {'a', QLatin1String("anoise")}, + {'a', QLatin1String("append")}, + {'a', QLatin1String("area")}, + {'a', QLatin1String("argsort")}, + {'a', QLatin1String("array")}, + {'a', QLatin1String("ashikhmin")}, + {'a', QLatin1String("asin")}, + {'a', QLatin1String("assert_enabled")}, + {'a', QLatin1String("assign")}, + {'a', QLatin1String("atan")}, + {'a', QLatin1String("atan2")}, + {'a', QLatin1String("atof")}, + {'a', QLatin1String("atoi")}, + {'a', QLatin1String("atten")}, + {'a', QLatin1String("attrib")}, + {'a', QLatin1String("attribclass")}, + {'a', QLatin1String("attribsize")}, + {'a', QLatin1String("attribtype")}, + {'a', QLatin1String("attribtypeinfo")}, + {'a', QLatin1String("avg")}, + {'b', QLatin1String("binput")}, + {'b', QLatin1String("blackbody")}, + {'b', QLatin1String("blinn")}, + {'b', QLatin1String("blinnBRDF")}, + {'b', QLatin1String("bouncelabel")}, + {'b', QLatin1String("bouncemask")}, + {'b', QLatin1String("bumpmap")}, + {'b', QLatin1String("bumpmapA")}, + {'b', QLatin1String("bumpmapB")}, + {'b', QLatin1String("bumpmapG")}, + {'b', QLatin1String("bumpmapL")}, + {'b', QLatin1String("bumpmapR")}, + {'b', QLatin1String("bumpname")}, + {'c', QLatin1String("cbrt")}, + {'c', QLatin1String("ceil")}, + {'c', QLatin1String("ch")}, + {'c', QLatin1String("ch3")}, + {'c', QLatin1String("ch4")}, + {'c', QLatin1String("chend")}, + {'c', QLatin1String("chendf")}, + {'c', QLatin1String("chendt")}, + {'c', QLatin1String("chf")}, + {'c', QLatin1String("chi")}, + {'c', QLatin1String("chinput")}, + {'c', QLatin1String("chname")}, + {'c', QLatin1String("chnumchan")}, + {'c', QLatin1String("chp")}, + {'c', QLatin1String("chr")}, + {'c', QLatin1String("chramp")}, + {'c', QLatin1String("chrate")}, + {'c', QLatin1String("chs")}, + {'c', QLatin1String("chsraw")}, + {'c', QLatin1String("chstart")}, + {'c', QLatin1String("chstartf")}, + {'c', QLatin1String("chstartt")}, + {'c', QLatin1String("chv")}, + {'c', QLatin1String("cinput")}, + {'c', QLatin1String("ckspline")}, + {'c', QLatin1String("clamp")}, + {'c', QLatin1String("clip")}, + {'c', QLatin1String("colormap")}, + {'c', QLatin1String("colorname")}, + {'c', QLatin1String("computenormal")}, + {'c', QLatin1String("concat")}, + {'c', QLatin1String("cone")}, + {'c', QLatin1String("cos")}, + {'c', QLatin1String("cosh")}, + {'c', QLatin1String("cracktransform")}, + {'c', QLatin1String("cross")}, + {'c', QLatin1String("cspline")}, + {'c', QLatin1String("ctransform")}, + {'c', QLatin1String("curlnoise")}, + {'c', QLatin1String("curlnoise2d")}, + {'c', QLatin1String("curlxnoise")}, + {'c', QLatin1String("curlxnoise2d")}, + {'c', QLatin1String("cvex_bsdf")}, + {'d', QLatin1String("degrees")}, + {'d', QLatin1String("depthmap")}, + {'d', QLatin1String("depthname")}, + {'d', QLatin1String("detail")}, + {'d', QLatin1String("detailattrib")}, + {'d', QLatin1String("detailattribsize")}, + {'d', QLatin1String("detailattribtype")}, + {'d', QLatin1String("detailattribtypeinfo")}, + {'d', QLatin1String("detailintrinsic")}, + {'d', QLatin1String("determinant")}, + {'d', QLatin1String("diffuse")}, + {'d', QLatin1String("diffuseBRDF")}, + {'d', QLatin1String("dihedral")}, + {'d', QLatin1String("dimport")}, + {'d', QLatin1String("distance")}, + {'d', QLatin1String("distance2")}, + {'d', QLatin1String("dot")}, + {'d', QLatin1String("dsmpixel")}, + {'e', QLatin1String("eigenvalues")}, + {'e', QLatin1String("endswith")}, + {'e', QLatin1String("environment")}, + {'e', QLatin1String("erf")}, + {'e', QLatin1String("erf_inv")}, + {'e', QLatin1String("erfc")}, + {'e', QLatin1String("error")}, + {'e', QLatin1String("eulertoquaternion")}, + {'e', QLatin1String("eval_bsdf")}, + {'e', QLatin1String("exp")}, + {'e', QLatin1String("expand_udim")}, + {'e', QLatin1String("expandpointgroup")}, + {'e', QLatin1String("expandprimgroup")}, + {'f', QLatin1String("fastshadow")}, + {'f', QLatin1String("filamentsample")}, + {'f', QLatin1String("file_stat")}, + {'f', QLatin1String("filtershadow")}, + {'f', QLatin1String("filterstep")}, + {'f', QLatin1String("find")}, + {'f', QLatin1String("findattribval")}, + {'f', QLatin1String("findattribvalcount")}, + {'f', QLatin1String("finput")}, + {'f', QLatin1String("fit")}, + {'f', QLatin1String("fit01")}, + {'f', QLatin1String("fit10")}, + {'f', QLatin1String("fit11")}, + {'f', QLatin1String("floor")}, + {'f', QLatin1String("flownoise")}, + {'f', QLatin1String("flowpnoise")}, + {'f', QLatin1String("frac")}, + {'f', QLatin1String("fresnel")}, + {'f', QLatin1String("fromNDC")}, + {'f', QLatin1String("frontface")}, + {'f', QLatin1String("fuzzify")}, + {'f', QLatin1String("fuzzy_and")}, + {'f', QLatin1String("fuzzy_defuzz_centroid")}, + {'f', QLatin1String("fuzzy_nand")}, + {'f', QLatin1String("fuzzy_nor")}, + {'f', QLatin1String("fuzzy_not")}, + {'f', QLatin1String("fuzzy_nxor")}, + {'f', QLatin1String("fuzzy_or")}, + {'f', QLatin1String("fuzzy_xor")}, + {'g', QLatin1String("geoself")}, + {'g', QLatin1String("getattrib")}, + {'g', QLatin1String("getattribute")}, + {'g', QLatin1String("getbbox")}, + {'g', QLatin1String("getblurP")}, + {'g', QLatin1String("getbounces")}, + {'g', QLatin1String("getbounds")}, + {'g', QLatin1String("getcomp")}, + {'g', QLatin1String("getcomponents")}, + {'g', QLatin1String("getderiv")}, + {'g', QLatin1String("getfogname")}, + {'g', QLatin1String("getglobalraylevel")}, + {'g', QLatin1String("getlight")}, + {'g', QLatin1String("getlightid")}, + {'g', QLatin1String("getlightname")}, + {'g', QLatin1String("getlights")}, + {'g', QLatin1String("getlightscope")}, + {'g', QLatin1String("getmaterial")}, + {'g', QLatin1String("getobjectname")}, + {'g', QLatin1String("getphotonlight")}, + {'g', QLatin1String("getpointbbox")}, + {'g', QLatin1String("getprimid")}, + {'g', QLatin1String("getptextureid")}, + {'g', QLatin1String("getraylevel")}, + {'g', QLatin1String("getrayweight")}, + {'g', QLatin1String("getsamplestore")}, + {'g', QLatin1String("getscope")}, + {'g', QLatin1String("getsmoothP")}, + {'g', QLatin1String("getspace")}, + {'g', QLatin1String("getuvobjects")}, + {'g', QLatin1String("getuvtangents")}, + {'g', QLatin1String("gradient")}, + {'h', QLatin1String("hair")}, + {'h', QLatin1String("hasattrib")}, + {'h', QLatin1String("hasdetailattrib")}, + {'h', QLatin1String("haslight")}, + {'h', QLatin1String("hasplane")}, + {'h', QLatin1String("haspointattrib")}, + {'h', QLatin1String("hasprimattrib")}, + {'h', QLatin1String("hasvertexattrib")}, + {'h', QLatin1String("hedge_dstpoint")}, + {'h', QLatin1String("hedge_dstvertex")}, + {'h', QLatin1String("hedge_equivcount")}, + {'h', QLatin1String("hedge_isequiv")}, + {'h', QLatin1String("hedge_isprimary")}, + {'h', QLatin1String("hedge_isvalid")}, + {'h', QLatin1String("hedge_next")}, + {'h', QLatin1String("hedge_nextequiv")}, + {'h', QLatin1String("hedge_postdstpoint")}, + {'h', QLatin1String("hedge_postdstvertex")}, + {'h', QLatin1String("hedge_presrcpoint")}, + {'h', QLatin1String("hedge_presrcvertex")}, + {'h', QLatin1String("hedge_prev")}, + {'h', QLatin1String("hedge_prim")}, + {'h', QLatin1String("hedge_primary")}, + {'h', QLatin1String("hedge_srcpoint")}, + {'h', QLatin1String("hedge_srcvertex")}, + {'h', QLatin1String("henyeygreenstein")}, + {'h', QLatin1String("hscript_noise")}, + {'h', QLatin1String("hscript_rand")}, + {'h', QLatin1String("hscript_snoise")}, + {'h', QLatin1String("hscript_sturb")}, + {'h', QLatin1String("hscript_turb")}, + {'h', QLatin1String("hsvtorgb")}, + {'i', QLatin1String("iaspect")}, + {'i', QLatin1String("ichname")}, + {'i', QLatin1String("ident")}, + {'i', QLatin1String("idtopoint")}, + {'i', QLatin1String("idtoprim")}, + {'i', QLatin1String("iend")}, + {'i', QLatin1String("iendtime")}, + {'i', QLatin1String("ihasplane")}, + {'i', QLatin1String("import")}, + {'i', QLatin1String("ingroup")}, + {'i', QLatin1String("inpointgroup")}, + {'i', QLatin1String("inprimgroup")}, + {'i', QLatin1String("insert")}, + {'i', QLatin1String("instance")}, + {'i', QLatin1String("interpolate")}, + {'i', QLatin1String("intersect")}, + {'i', QLatin1String("intersect_all")}, + {'i', QLatin1String("intersect_lights")}, + {'i', QLatin1String("inumplanes")}, + {'i', QLatin1String("invert")}, + {'i', QLatin1String("invertexgroup")}, + {'i', QLatin1String("iplaneindex")}, + {'i', QLatin1String("iplanename")}, + {'i', QLatin1String("iplanesize")}, + {'i', QLatin1String("irate")}, + {'i', QLatin1String("irradiance")}, + {'i', QLatin1String("isalpha")}, + {'i', QLatin1String("isbound")}, + {'i', QLatin1String("isconnected")}, + {'i', QLatin1String("isdigit")}, + {'i', QLatin1String("isfinite")}, + {'i', QLatin1String("isfogray")}, + {'i', QLatin1String("isframes")}, + {'i', QLatin1String("isnan")}, + {'i', QLatin1String("isotropic")}, + {'i', QLatin1String("israytracing")}, + {'i', QLatin1String("issamples")}, + {'i', QLatin1String("isseconds")}, + {'i', QLatin1String("isshadowray")}, + {'i', QLatin1String("istart")}, + {'i', QLatin1String("istarttime")}, + {'i', QLatin1String("isuvrendering")}, + {'i', QLatin1String("isvalidindex")}, + {'i', QLatin1String("isvarying")}, + {'i', QLatin1String("itoa")}, + {'i', QLatin1String("ixres")}, + {'i', QLatin1String("iyres")}, + {'j', QLatin1String("join")}, + {'k', QLatin1String("kspline")}, + {'l', QLatin1String("len")}, + {'l', QLatin1String("length")}, + {'l', QLatin1String("length2")}, + {'l', QLatin1String("lerp")}, + {'l', QLatin1String("lightid")}, + {'l', QLatin1String("limit_sample_space")}, + {'l', QLatin1String("limport")}, + {'l', QLatin1String("lkspline")}, + {'l', QLatin1String("log")}, + {'l', QLatin1String("log10")}, + {'l', QLatin1String("lookat")}, + {'l', QLatin1String("lspline")}, + {'l', QLatin1String("lstrip")}, + {'l', QLatin1String("luminance")}, + {'l', QLatin1String("lumname")}, + {'m', QLatin1String("makebasis")}, + {'m', QLatin1String("maketransform")}, + {'m', QLatin1String("maskname")}, + {'m', QLatin1String("match")}, + {'m', QLatin1String("matchvex_blinn")}, + {'m', QLatin1String("matchvex_specular")}, + {'m', QLatin1String("mattrib")}, + {'m', QLatin1String("max")}, + {'m', QLatin1String("mdensity")}, + {'m', QLatin1String("metaimport")}, + {'m', QLatin1String("metamarch")}, + {'m', QLatin1String("metanext")}, + {'m', QLatin1String("metastart")}, + {'m', QLatin1String("metaweight")}, + {'m', QLatin1String("min")}, + {'m', QLatin1String("minpos")}, + {'m', QLatin1String("mspace")}, + {'n', QLatin1String("nametopoint")}, + {'n', QLatin1String("nametoprim")}, + {'n', QLatin1String("nbouncetypes")}, + {'n', QLatin1String("nearpoint")}, + {'n', QLatin1String("nearpoints")}, + {'n', QLatin1String("neighbour")}, + {'n', QLatin1String("neighbourcount")}, + {'n', QLatin1String("neighbours")}, + {'n', QLatin1String("newgroup")}, + {'n', QLatin1String("newsampler")}, + {'n', QLatin1String("nextsample")}, + {'n', QLatin1String("ninput")}, + {'n', QLatin1String("noise")}, + {'n', QLatin1String("noised")}, + {'n', QLatin1String("normal_bsdf")}, + {'n', QLatin1String("normalize")}, + {'n', QLatin1String("normalname")}, + {'n', QLatin1String("npoints")}, + {'n', QLatin1String("npointsgroup")}, + {'n', QLatin1String("nprimitives")}, + {'n', QLatin1String("nprimitivesgroup")}, + {'n', QLatin1String("nrandom")}, + {'n', QLatin1String("ntransform")}, + {'n', QLatin1String("nuniqueval")}, + {'n', QLatin1String("nvertices")}, + {'n', QLatin1String("nverticesgroup")}, + {'o', QLatin1String("occlusion")}, + {'o', QLatin1String("onoise")}, + {'o', QLatin1String("opdigits")}, + {'o', QLatin1String("opend")}, + {'o', QLatin1String("opfullpath")}, + {'o', QLatin1String("opstart")}, + {'o', QLatin1String("optransform")}, + {'o', QLatin1String("ord")}, + {'o', QLatin1String("osd_facecount")}, + {'o', QLatin1String("osd_firstpatch")}, + {'o', QLatin1String("osd_limitsurface")}, + {'o', QLatin1String("osd_limitsurfacevertex")}, + {'o', QLatin1String("osd_patchcount")}, + {'o', QLatin1String("osd_patches")}, + {'o', QLatin1String("outerproduct")}, + {'o', QLatin1String("ow_nspace")}, + {'o', QLatin1String("ow_space")}, + {'o', QLatin1String("ow_vspace")}, + {'p', QLatin1String("pack_inttosafefloat")}, + {'p', QLatin1String("pathtrace")}, + {'p', QLatin1String("pcclose")}, + {'p', QLatin1String("pcconvex")}, + {'p', QLatin1String("pcexport")}, + {'p', QLatin1String("pcfarthest")}, + {'p', QLatin1String("pcfilter")}, + {'p', QLatin1String("pcfind")}, + {'p', QLatin1String("pcfind_radius")}, + {'p', QLatin1String("pcgenerate")}, + {'p', QLatin1String("pcimport")}, + {'p', QLatin1String("pcimportbyidx3")}, + {'p', QLatin1String("pcimportbyidx4")}, + {'p', QLatin1String("pcimportbyidxf")}, + {'p', QLatin1String("pcimportbyidxi")}, + {'p', QLatin1String("pcimportbyidxp")}, + {'p', QLatin1String("pcimportbyidxs")}, + {'p', QLatin1String("pcimportbyidxv")}, + {'p', QLatin1String("pciterate")}, + {'p', QLatin1String("pcnumfound")}, + {'p', QLatin1String("pcopen")}, + {'p', QLatin1String("pcopenlod")}, + {'p', QLatin1String("pcsampleleaf")}, + {'p', QLatin1String("pcsize")}, + {'p', QLatin1String("pcunshaded")}, + {'p', QLatin1String("pcwrite")}, + {'p', QLatin1String("pgfind")}, + {'p', QLatin1String("phong")}, + {'p', QLatin1String("phongBRDF")}, + {'p', QLatin1String("phonglobe")}, + {'p', QLatin1String("photonmap")}, + {'p', QLatin1String("planeindex")}, + {'p', QLatin1String("planename")}, + {'p', QLatin1String("planesize")}, + {'p', QLatin1String("pluralize")}, + {'p', QLatin1String("pnoise")}, + {'p', QLatin1String("point")}, + {'p', QLatin1String("pointattrib")}, + {'p', QLatin1String("pointattribsize")}, + {'p', QLatin1String("pointattribtype")}, + {'p', QLatin1String("pointattribtypeinfo")}, + {'p', QLatin1String("pointedge")}, + {'p', QLatin1String("pointhedge")}, + {'p', QLatin1String("pointhedgenext")}, + {'p', QLatin1String("pointname")}, + {'p', QLatin1String("pointprims")}, + {'p', QLatin1String("pointvertex")}, + {'p', QLatin1String("pointvertices")}, + {'p', QLatin1String("polardecomp")}, + {'p', QLatin1String("pop")}, + {'p', QLatin1String("pow")}, + {'p', QLatin1String("prim")}, + {'p', QLatin1String("prim_attribute")}, + {'p', QLatin1String("prim_normal")}, + {'p', QLatin1String("primattrib")}, + {'p', QLatin1String("primattribsize")}, + {'p', QLatin1String("primattribtype")}, + {'p', QLatin1String("primattribtypeinfo")}, + {'p', QLatin1String("primhedge")}, + {'p', QLatin1String("primintrinsic")}, + {'p', QLatin1String("primpoint")}, + {'p', QLatin1String("primpoints")}, + {'p', QLatin1String("primuv")}, + {'p', QLatin1String("primvertex")}, + {'p', QLatin1String("primvertexcount")}, + {'p', QLatin1String("primvertices")}, + {'p', QLatin1String("print_once")}, + {'p', QLatin1String("printf")}, + {'p', QLatin1String("product")}, + {'p', QLatin1String("ptexture")}, + {'p', QLatin1String("ptlined")}, + {'p', QLatin1String("ptransform")}, + {'p', QLatin1String("push")}, + {'q', QLatin1String("qconvert")}, + {'q', QLatin1String("qdistance")}, + {'q', QLatin1String("qinvert")}, + {'q', QLatin1String("qmultiply")}, + {'q', QLatin1String("qrotate")}, + {'q', QLatin1String("quaternion")}, + {'r', QLatin1String("radians")}, + {'r', QLatin1String("rand")}, + {'r', QLatin1String("random")}, + {'r', QLatin1String("random_fhash")}, + {'r', QLatin1String("random_ihash")}, + {'r', QLatin1String("random_shash")}, + {'r', QLatin1String("random_sobol")}, + {'r', QLatin1String("rawbumpmap")}, + {'r', QLatin1String("rawbumpmapA")}, + {'r', QLatin1String("rawbumpmapB")}, + {'r', QLatin1String("rawbumpmapG")}, + {'r', QLatin1String("rawbumpmapL")}, + {'r', QLatin1String("rawbumpmapR")}, + {'r', QLatin1String("rawcolormap")}, + {'r', QLatin1String("rayhittest")}, + {'r', QLatin1String("rayimport")}, + {'r', QLatin1String("re_find")}, + {'r', QLatin1String("re_findall")}, + {'r', QLatin1String("re_match")}, + {'r', QLatin1String("re_replace")}, + {'r', QLatin1String("re_split")}, + {'r', QLatin1String("reflect")}, + {'r', QLatin1String("reflectlight")}, + {'r', QLatin1String("refract")}, + {'r', QLatin1String("refractlight")}, + {'r', QLatin1String("relativepath")}, + {'r', QLatin1String("relbbox")}, + {'r', QLatin1String("relpointbbox")}, + {'r', QLatin1String("removegroup")}, + {'r', QLatin1String("removeindex")}, + {'r', QLatin1String("removepoint")}, + {'r', QLatin1String("removeprim")}, + {'r', QLatin1String("removevalue")}, + {'r', QLatin1String("renderstate")}, + {'r', QLatin1String("reorder")}, + {'r', QLatin1String("resample_linear")}, + {'r', QLatin1String("resize")}, + {'r', QLatin1String("resolvemissedray")}, + {'r', QLatin1String("reverse")}, + {'r', QLatin1String("rgbtohsv")}, + {'r', QLatin1String("rgbtoxyz")}, + {'r', QLatin1String("rint")}, + {'r', QLatin1String("rotate")}, + {'r', QLatin1String("rotate_x_to")}, + {'r', QLatin1String("rstrip")}, + {'s', QLatin1String("sample_bsdf")}, + {'s', QLatin1String("sample_cauchy")}, + {'s', QLatin1String("sample_circle_arc")}, + {'s', QLatin1String("sample_circle_edge_uniform")}, + {'s', QLatin1String("sample_circle_slice")}, + {'s', QLatin1String("sample_circle_uniform")}, + {'s', QLatin1String("sample_direction_cone")}, + {'s', QLatin1String("sample_direction_uniform")}, + {'s', QLatin1String("sample_discrete")}, + {'s', QLatin1String("sample_exponential")}, + {'s', QLatin1String("sample_geometry")}, + {'s', QLatin1String("sample_hemisphere")}, + {'s', QLatin1String("sample_hypersphere_cone")}, + {'s', QLatin1String("sample_hypersphere_uniform")}, + {'s', QLatin1String("sample_light")}, + {'s', QLatin1String("sample_lognormal")}, + {'s', QLatin1String("sample_lognormal_by_median")}, + {'s', QLatin1String("sample_normal")}, + {'s', QLatin1String("sample_orientation_cone")}, + {'s', QLatin1String("sample_orientation_uniform")}, + {'s', QLatin1String("sample_photon")}, + {'s', QLatin1String("sample_sphere_cone")}, + {'s', QLatin1String("sample_sphere_uniform")}, + {'s', QLatin1String("sampledisk")}, + {'s', QLatin1String("scale")}, + {'s', QLatin1String("select")}, + {'s', QLatin1String("sensor_panorama_create")}, + {'s', QLatin1String("sensor_panorama_getcolor")}, + {'s', QLatin1String("sensor_panorama_getcone")}, + {'s', QLatin1String("sensor_panorama_getdepth")}, + {'s', QLatin1String("sensor_save")}, + {'s', QLatin1String("serialize")}, + {'s', QLatin1String("set")}, + {'s', QLatin1String("setagentclipnames")}, + {'s', QLatin1String("setagentcliptimes")}, + {'s', QLatin1String("setagentclipweights")}, + {'s', QLatin1String("setagentcollisionlayer")}, + {'s', QLatin1String("setagentcurrentlayer")}, + {'s', QLatin1String("setagentlocaltransform")}, + {'s', QLatin1String("setagentlocaltransforms")}, + {'s', QLatin1String("setagentworldtransform")}, + {'s', QLatin1String("setagentworldtransforms")}, + {'s', QLatin1String("setattrib")}, + {'s', QLatin1String("setattribtypeinfo")}, + {'s', QLatin1String("setcomp")}, + {'s', QLatin1String("setcurrentlight")}, + {'s', QLatin1String("setdetailattrib")}, + {'s', QLatin1String("setpointattrib")}, + {'s', QLatin1String("setpointgroup")}, + {'s', QLatin1String("setprimattrib")}, + {'s', QLatin1String("setprimgroup")}, + {'s', QLatin1String("setprimintrinsic")}, + {'s', QLatin1String("setprimvertex")}, + {'s', QLatin1String("setsamplestore")}, + {'s', QLatin1String("setvertexattrib")}, + {'s', QLatin1String("setvertexgroup")}, + {'s', QLatin1String("setvertexpoint")}, + {'s', QLatin1String("shadow")}, + {'s', QLatin1String("shadow_light")}, + {'s', QLatin1String("shadowmap")}, + {'s', QLatin1String("shimport")}, + {'s', QLatin1String("shl")}, + {'s', QLatin1String("shr")}, + {'s', QLatin1String("shrz")}, + {'s', QLatin1String("sign")}, + {'s', QLatin1String("simport")}, + {'s', QLatin1String("sin")}, + {'s', QLatin1String("sinh")}, + {'s', QLatin1String("sleep")}, + {'s', QLatin1String("slerp")}, + {'s', QLatin1String("slice")}, + {'s', QLatin1String("slideframe")}, + {'s', QLatin1String("smooth")}, + {'s', QLatin1String("smoothrotation")}, + {'s', QLatin1String("snoise")}, + {'s', QLatin1String("solvecubic")}, + {'s', QLatin1String("solvepoly")}, + {'s', QLatin1String("solvequadratic")}, + {'s', QLatin1String("sort")}, + {'s', QLatin1String("specular")}, + {'s', QLatin1String("specularBRDF")}, + {'s', QLatin1String("spline")}, + {'s', QLatin1String("split")}, + {'s', QLatin1String("splitpath")}, + {'s', QLatin1String("sprintf")}, + {'s', QLatin1String("sqrt")}, + {'s', QLatin1String("startswith")}, + {'s', QLatin1String("storelightexport")}, + {'s', QLatin1String("strip")}, + {'s', QLatin1String("strlen")}, + {'s', QLatin1String("sum")}, + {'s', QLatin1String("switch")}, + {'s', QLatin1String("swizzle")}, + {'t', QLatin1String("tan")}, + {'t', QLatin1String("tanh")}, + {'t', QLatin1String("tet_adjacent")}, + {'t', QLatin1String("tet_faceindex")}, + {'t', QLatin1String("teximport")}, + {'t', QLatin1String("texprintf")}, + {'t', QLatin1String("texture")}, + {'t', QLatin1String("texture3d")}, + {'t', QLatin1String("texture3dBox")}, + {'t', QLatin1String("titlecase")}, + {'t', QLatin1String("toNDC")}, + {'t', QLatin1String("tolower")}, + {'t', QLatin1String("toupper")}, + {'t', QLatin1String("trace")}, + {'t', QLatin1String("translate")}, + {'t', QLatin1String("translucent")}, + {'t', QLatin1String("transpose")}, + {'t', QLatin1String("trunc")}, + {'t', QLatin1String("tw_nspace")}, + {'t', QLatin1String("tw_space")}, + {'t', QLatin1String("tw_vspace")}, + {'u', QLatin1String("uniqueval")}, + {'u', QLatin1String("unpack_intfromsafefloat")}, + {'u', QLatin1String("unserialize")}, + {'u', QLatin1String("upush")}, + {'u', QLatin1String("uvunwrap")}, + {'v', QLatin1String("variance")}, + {'v', QLatin1String("velocityname")}, + {'v', QLatin1String("vertex")}, + {'v', QLatin1String("vertexattrib")}, + {'v', QLatin1String("vertexattribsize")}, + {'v', QLatin1String("vertexattribtype")}, + {'v', QLatin1String("vertexattribtypeinfo")}, + {'v', QLatin1String("vertexhedge")}, + {'v', QLatin1String("vertexindex")}, + {'v', QLatin1String("vertexnext")}, + {'v', QLatin1String("vertexpoint")}, + {'v', QLatin1String("vertexprev")}, + {'v', QLatin1String("vertexprim")}, + {'v', QLatin1String("vertexprimindex")}, + {'v', QLatin1String("vnoise")}, + {'v', QLatin1String("volume")}, + {'v', QLatin1String("volumegradient")}, + {'v', QLatin1String("volumeindex")}, + {'v', QLatin1String("volumeindexorigin")}, + {'v', QLatin1String("volumeindextopos")}, + {'v', QLatin1String("volumeindexv")}, + {'v', QLatin1String("volumepostoindex")}, + {'v', QLatin1String("volumeres")}, + {'v', QLatin1String("volumesample")}, + {'v', QLatin1String("volumesamplev")}, + {'v', QLatin1String("vtransform")}, + {'w', QLatin1String("warning")}, + {'w', QLatin1String("wireblinn")}, + {'w', QLatin1String("wirediffuse")}, + {'w', QLatin1String("wnoise")}, + {'w', QLatin1String("wo_nspace")}, + {'w', QLatin1String("wo_space")}, + {'w', QLatin1String("wo_vspace")}, + {'w', QLatin1String("writepixel")}, + {'w', QLatin1String("wt_nspace")}, + {'w', QLatin1String("wt_space")}, + {'w', QLatin1String("wt_vspace")}, + {'x', QLatin1String("xnoise")}, + {'x', QLatin1String("xnoised")}, + {'x', QLatin1String("xyzdist")}, + {'x', QLatin1String("xyztorgb")}}; + vex_other = { + {('d'), QLatin1String("define")}, {('e'), QLatin1String("else")}, + {('e'), QLatin1String("endif")}, {('i'), QLatin1String("if")}, + {('i'), QLatin1String("ifdef")}, {('i'), QLatin1String("ifndef")}, + {('i'), QLatin1String("include")}, {('p'), QLatin1String("pragma")}, + {('u'), QLatin1String("undef")}, + }; +} +void loadVEXData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!vexDataInitialized) { + initVEXData(); + vexDataInitialized = true; + } + types = vex_types; + keywords = vex_keywords; + builtin = vex_builtin; + literals = vex_literals; + other = vex_other; +} + +/********************************************************/ +/*** CMAKE DATA ***************************************/ +/********************************************************/ +static bool cmakeDataInitialized = false; +static QMultiHash cmake_keywords; +static QMultiHash cmake_types; +static QMultiHash cmake_literals; +static QMultiHash cmake_builtin; +static QMultiHash cmake_other; +void initCMakeData() { + cmake_keywords = {{'b', QLatin1String("break")}, + {'c', QLatin1String("cmake_host_system_information")}, + {'c', QLatin1String("cmake_minimum_required")}, + {'c', QLatin1String("cmake_parse_arguments")}, + {'c', QLatin1String("cmake_policy")}, + {'c', QLatin1String("configure_file")}, + {'c', QLatin1String("continue")}, + {'e', QLatin1String("elseif")}, + {'e', QLatin1String("else")}, + {'e', QLatin1String("endforeach")}, + {'e', QLatin1String("endfunction")}, + {'e', QLatin1String("endif")}, + {'e', QLatin1String("endmacro")}, + {'e', QLatin1String("endwhile")}, + {'e', QLatin1String("execute_process")}, + {'f', QLatin1String("file")}, + {'f', QLatin1String("find_file")}, + {'f', QLatin1String("find_library")}, + {'f', QLatin1String("find_package")}, + {'f', QLatin1String("find_path")}, + {'f', QLatin1String("find_program")}, + {'f', QLatin1String("foreach")}, + {'f', QLatin1String("function")}, + {'g', QLatin1String("get_cmake_property")}, + {'g', QLatin1String("get_directory_property")}, + {'g', QLatin1String("get_filename_component")}, + {'g', QLatin1String("get_property")}, + {'i', QLatin1String("if")}, + {'i', QLatin1String("include")}, + {'i', QLatin1String("include_guard")}, + {'l', QLatin1String("list")}, + {'m', QLatin1String("macro")}, + {'m', QLatin1String("mark_as_advanced")}, + {'m', QLatin1String("math")}, + {'m', QLatin1String("message")}, + {'o', QLatin1String("option")}, + {'r', QLatin1String("return")}, + {'s', QLatin1String("separate_arguments")}, + {'s', QLatin1String("set_directory_properties")}, + {'s', QLatin1String("set")}, + {'s', QLatin1String("set_property")}, + {'s', QLatin1String("site_name")}, + {'s', QLatin1String("string")}, + {'u', QLatin1String("unset")}, + {'v', QLatin1String("variable_watch")}, + {'w', QLatin1String("while")}, + {'a', QLatin1String("add_compile_definitions")}, + {'a', QLatin1String("add_compile_options")}, + {'A', QLatin1String("ADD_COMPILE_OPTIONS")}, + {'a', QLatin1String("add_custom_command")}, + {'a', QLatin1String("add_custom_target")}, + {'a', QLatin1String("add_definitions")}, + {'a', QLatin1String("add_dependencies")}, + {'a', QLatin1String("add_executable")}, + {'a', QLatin1String("add_library")}, + {'a', QLatin1String("add_link_options")}, + {'a', QLatin1String("add_subdirectory")}, + {'a', QLatin1String("add_test")}, + {'a', QLatin1String("aux_source_directory")}, + {'b', QLatin1String("build_command")}, + {'c', QLatin1String("create_test_sourcelist")}, + {'d', QLatin1String("define_property")}, + {'e', QLatin1String("enable_language")}, + {'e', QLatin1String("enable_testing")}, + {'e', QLatin1String("export")}, + {'f', QLatin1String("fltk_wrap_ui")}, + {'g', QLatin1String("get_source_file_property")}, + {'g', QLatin1String("get_target_property")}, + {'g', QLatin1String("get_test_property")}, + {'i', QLatin1String("include_directories")}, + {'i', QLatin1String("include_external_msproject")}, + {'i', QLatin1String("include_regular_expression")}, + {'i', QLatin1String("install")}, + {'l', QLatin1String("link_directories")}, + {'l', QLatin1String("link_libraries")}, + {'l', QLatin1String("load_cache")}, + {'p', QLatin1String("project")}, + {'q', QLatin1String("qt_wrap_cpp")}, + {'q', QLatin1String("qt_wrap_ui")}, + {'r', QLatin1String("remove_definitions")}, + {'s', QLatin1String("set_source_files_properties")}, + {'s', QLatin1String("set_target_properties")}, + {'s', QLatin1String("set_tests_properties")}, + {'s', QLatin1String("source_group")}, + {'t', QLatin1String("target_compile_definitions")}, + {'t', QLatin1String("target_compile_features")}, + {'t', QLatin1String("target_compile_options")}, + {'t', QLatin1String("target_include_directories")}, + {'t', QLatin1String("target_link_directories")}, + {'t', QLatin1String("target_link_libraries")}, + {'t', QLatin1String("target_link_options")}, + {'t', QLatin1String("target_sources")}, + {'t', QLatin1String("try_compile")}, + {'t', QLatin1String("try_run")}, + {'c', QLatin1String("ctest_build")}, + {'c', QLatin1String("ctest_configure")}, + {'c', QLatin1String("ctest_coverage")}, + {'c', QLatin1String("ctest_empty_binary_directory")}, + {'c', QLatin1String("ctest_memcheck")}, + {'c', QLatin1String("ctest_read_custom_files")}, + {'c', QLatin1String("ctest_run_script")}, + {'c', QLatin1String("ctest_sleep")}, + {'c', QLatin1String("ctest_start")}, + {'c', QLatin1String("ctest_submit")}, + {'c', QLatin1String("ctest_test")}, + {'c', QLatin1String("ctest_update")}, + {'c', QLatin1String("ctest_upload")}, + {'b', QLatin1String("build_name")}, + {'e', QLatin1String("exec_program")}, + {'e', QLatin1String("export_library_dependencies")}, + {'i', QLatin1String("install_files")}, + {'i', QLatin1String("install_programs")}, + {'i', QLatin1String("install_targets")}, + {'l', QLatin1String("load_command")}, + {'m', QLatin1String("make_directory")}, + {'o', QLatin1String("output_required_files")}, + {'r', QLatin1String("remove")}, + {'s', QLatin1String("subdir_depends")}, + {'s', QLatin1String("subdirs")}, + {'u', QLatin1String("use_mangled_mesa")}, + {'u', QLatin1String("utility_source")}, + {'v', QLatin1String("variable_requires")}, + {'w', QLatin1String("write_file")}, + {'q', QLatin1String("qt5_use_modules")}, + {'q', QLatin1String("qt5_use_package")}, + {'q', QLatin1String("qt5_wrap_cpp")}, + {'a', QLatin1String("and")}, + {'o', QLatin1String("or")}, + {'n', QLatin1String("not")}, + {'c', QLatin1String("command")}, + {'p', QLatin1String("policy")}, + {'t', QLatin1String("target")}, + {'t', QLatin1String("test")}, + {'e', QLatin1String("exists")}, + {'i', QLatin1String("is_newer_than")}, + {'i', QLatin1String("is_directory")}, + {'i', QLatin1String("is_symlink")}, + {'i', QLatin1String("is_absolute")}, + {'m', QLatin1String("matches")}, + {'l', QLatin1String("less")}, + {'g', QLatin1String("greater")}, + {'e', QLatin1String("equal")}, + {'l', QLatin1String("less_equal")}, + {'g', QLatin1String("greater_equal")}, + {'s', QLatin1String("strless")}, + {'s', QLatin1String("strgreater")}, + {'s', QLatin1String("strequal")}, + {'s', QLatin1String("strless_equal")}, + {'s', QLatin1String("strgreater_equal")}, + {'v', QLatin1String("version_less")}, + {'v', QLatin1String("version_greater")}, + {'v', QLatin1String("version_equal")}, + {'v', QLatin1String("version_less_equal")}, + {'v', QLatin1String("version_greater_equal")}, + {'i', QLatin1String("in_list")}, + {'d', QLatin1String("defined")}}; + cmake_types = {}; + cmake_literals = { + {'o', QLatin1String("on")}, {'o', QLatin1String("off")}, + {'O', QLatin1String("ON")}, {'O', QLatin1String("OFF")}, + {'t', QLatin1String("true")}, {'f', QLatin1String("false")}, + {'T', QLatin1String("TRUE")}, {'F', QLatin1String("FALSE")}}; + cmake_builtin = { + {'A', QLatin1String("ALLOW_DUPLICATE_CUSTOM_TARGETS")}, + {'A', QLatin1String("AUTOGEN_TARGETS_FOLDER")}, + {'A', QLatin1String("AUTOMOC_TARGETS_FOLDER")}, + {'D', QLatin1String("DEBUG_CONFIGURATIONS")}, + {'D', QLatin1String("DISABLED_FEATURES")}, + {'E', QLatin1String("ENABLED_FEATURES")}, + {'E', QLatin1String("ENABLED_LANGUAGES")}, + {'F', QLatin1String("FIND_LIBRARY_USE_LIB64_PATHS")}, + {'F', QLatin1String("FIND_LIBRARY_USE_OPENBSD_VERSIONING")}, + {'G', QLatin1String("GLOBAL_DEPENDS_DEBUG_MODE")}, + {'G', QLatin1String("GLOBAL_DEPENDS_NO_CYCLES")}, + {'I', QLatin1String("IN_TRY_COMPILE")}, + {'P', QLatin1String("PACKAGES_FOUND")}, + {'P', QLatin1String("PACKAGES_NOT_FOUND")}, + {'J', QLatin1String("JOB_POOLS")}, + {'P', QLatin1String("PREDEFINED_TARGETS_FOLDER")}, + {'E', QLatin1String("ECLIPSE_EXTRA_NATURES")}, + {'R', QLatin1String("REPORT_UNDEFINED_PROPERTIES")}, + {'R', QLatin1String("RULE_LAUNCH_COMPILE")}, + {'R', QLatin1String("RULE_LAUNCH_CUSTOM")}, + {'R', QLatin1String("RULE_LAUNCH_LINK")}, + {'R', QLatin1String("RULE_MESSAGES")}, + {'T', QLatin1String("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS")}, + {'T', QLatin1String("TARGET_SUPPORTS_SHARED_LIBS")}, + {'U', QLatin1String("USE_FOLDERS")}, + {'A', QLatin1String("ADDITIONAL_MAKE_CLEAN_FILES")}, + {'C', QLatin1String("CACHE_VARIABLES")}, + {'C', QLatin1String("CLEAN_NO_CUSTOM")}, + {'C', QLatin1String("CMAKE_CONFIGURE_DEPENDS")}, + {'C', QLatin1String("COMPILE_DEFINITIONS")}, + {'C', QLatin1String("COMPILE_OPTIONS")}, + {'D', QLatin1String("DEFINITIONS")}, + {'E', QLatin1String("EXCLUDE_FROM_ALL")}, + {'I', QLatin1String("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")}, + {'I', QLatin1String("INCLUDE_DIRECTORIES")}, + {'I', QLatin1String("INCLUDE_REGULAR_EXPRESSION")}, + {'I', QLatin1String("INTERPROCEDURAL_OPTIMIZATION")}, + {'L', QLatin1String("LINK_DIRECTORIES")}, + {'L', QLatin1String("LISTFILE_STACK")}, + {'M', QLatin1String("MACROS")}, + {'P', QLatin1String("PARENT_DIRECTORY")}, + {'R', QLatin1String("RULE_LAUNCH_COMPILE")}, + {'R', QLatin1String("RULE_LAUNCH_CUSTOM")}, + {'R', QLatin1String("RULE_LAUNCH_LINK")}, + {'T', QLatin1String("TEST_INCLUDE_FILE")}, + {'V', QLatin1String("VARIABLES")}, + {'A', QLatin1String("ALIASED_TARGET")}, + {'A', QLatin1String("ARCHIVE_OUTPUT_DIRECTORY")}, + {'A', QLatin1String("ARCHIVE_OUTPUT_NAME")}, + {'A', QLatin1String("AUTOGEN_TARGET_DEPENDS")}, + {'A', QLatin1String("AUTOMOC_MOC_OPTIONS")}, + {'A', QLatin1String("AUTOMOC")}, + {'A', QLatin1String("AUTOUIC")}, + {'A', QLatin1String("AUTOUIC_OPTIONS")}, + {'A', QLatin1String("AUTORCC")}, + {'A', QLatin1String("AUTORCC_OPTIONS")}, + {'B', QLatin1String("BUILD_WITH_INSTALL_RPATH")}, + {'B', QLatin1String("BUNDLE_EXTENSION")}, + {'B', QLatin1String("BUNDLE")}, + {'C', QLatin1String("COMPATIBLE_INTERFACE_BOOL")}, + {'C', QLatin1String("COMPATIBLE_INTERFACE_NUMBER_MAX")}, + {'C', QLatin1String("COMPATIBLE_INTERFACE_NUMBER_MIN")}, + {'C', QLatin1String("COMPATIBLE_INTERFACE_STRING")}, + {'C', QLatin1String("COMPILE_DEFINITIONS")}, + {'C', QLatin1String("COMPILE_FLAGS")}, + {'C', QLatin1String("COMPILE_OPTIONS")}, + {'D', QLatin1String("DEBUG_POSTFIX")}, + {'D', QLatin1String("DEFINE_SYMBOL")}, + {'E', QLatin1String("EchoString")}, + {'E', QLatin1String("ENABLE_EXPORTS")}, + {'E', QLatin1String("EXCLUDE_FROM_ALL")}, + {'E', QLatin1String("EXCLUDE_FROM_DEFAULT_BUILD")}, + {'E', QLatin1String("EXPORT_NAME")}, + {'F', QLatin1String("FOLDER")}, + {'F', QLatin1String("Fortran_FORMAT")}, + {'F', QLatin1String("Fortran_MODULE_DIRECTORY")}, + {'F', QLatin1String("FRAMEWORK")}, + {'G', QLatin1String("GENERATOR_FILE_NAME")}, + {'G', QLatin1String("GNUtoMS")}, + {'H', QLatin1String("HAS_CXX")}, + {'I', QLatin1String("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")}, + {'I', QLatin1String("IMPORTED_CONFIGURATIONS")}, + {'I', QLatin1String("IMPORTED_IMPLIB")}, + {'I', QLatin1String("IMPORTED_LINK_DEPENDENT_LIBRARIES")}, + {'I', QLatin1String("IMPORTED_LINK_INTERFACE_LANGUAGES")}, + {'I', QLatin1String("IMPORTED_LINK_INTERFACE_LIBRARIES")}, + {'I', QLatin1String("IMPORTED_LINK_INTERFACE_MULTIPLICITY")}, + {'I', QLatin1String("IMPORTED_LOCATION")}, + {'I', QLatin1String("IMPORTED_NO_SONAME")}, + {'I', QLatin1String("IMPORTED")}, + {'I', QLatin1String("IMPORTED_SONAME")}, + {'I', QLatin1String("IMPORT_PREFIX")}, + {'I', QLatin1String("IMPORT_SUFFIX")}, + {'I', QLatin1String("INCLUDE_DIRECTORIES")}, + {'I', QLatin1String("INSTALL_NAME_DIR")}, + {'I', QLatin1String("INSTALL_RPATH")}, + {'I', QLatin1String("INSTALL_RPATH_USE_LINK_PATH")}, + {'I', QLatin1String("INTERFACE_AUTOUIC_OPTIONS")}, + {'I', QLatin1String("INTERFACE_COMPILE_DEFINITIONS")}, + {'I', QLatin1String("INTERFACE_COMPILE_OPTIONS")}, + {'I', QLatin1String("INTERFACE_INCLUDE_DIRECTORIES")}, + {'I', QLatin1String("INTERFACE_LINK_LIBRARIES")}, + {'I', QLatin1String("INTERFACE_POSITION_INDEPENDENT_CODE")}, + {'I', QLatin1String("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")}, + {'I', QLatin1String("INTERPROCEDURAL_OPTIMIZATION")}, + {'J', QLatin1String("JOB_POOL_COMPILE")}, + {'J', QLatin1String("JOB_POOL_LINK")}, + {'L', QLatin1String("LABELS")}, + {'L', QLatin1String("LIBRARY_OUTPUT_DIRECTORY")}, + {'L', QLatin1String("LIBRARY_OUTPUT_NAME")}, + {'L', QLatin1String("LINK_DEPENDS_NO_SHARED")}, + {'L', QLatin1String("LINK_DEPENDS")}, + {'L', QLatin1String("LINKER_LANGUAGE")}, + {'L', QLatin1String("LINK_FLAGS")}, + {'L', QLatin1String("LINK_INTERFACE_LIBRARIES")}, + {'L', QLatin1String("LINK_INTERFACE_MULTIPLICITY")}, + {'L', QLatin1String("LINK_LIBRARIES")}, + {'L', QLatin1String("LINK_SEARCH_END_STATIC")}, + {'L', QLatin1String("LINK_SEARCH_START_STATIC")}, + {'L', QLatin1String("LOCATION")}, + {'M', QLatin1String("MACOSX_BUNDLE_INFO_PLIST")}, + {'M', QLatin1String("MACOSX_BUNDLE")}, + {'M', QLatin1String("MACOSX_FRAMEWORK_INFO_PLIST")}, + {'M', QLatin1String("MACOSX_RPATH")}, + // {'N', QLatin1String("NAME")}, + {'N', QLatin1String("NO_SONAME")}, + {'N', QLatin1String("NO_SYSTEM_FROM_IMPORTED")}, + {'O', QLatin1String("OSX_ARCHITECTURES")}, + {'O', QLatin1String("OUTPUT_NAME")}, + {'P', QLatin1String("PDB_NAME")}, + {'P', QLatin1String("PDB_OUTPUT_DIRECTORY")}, + {'P', QLatin1String("POSITION_INDEPENDENT_CODE")}, + {'P', QLatin1String("POST_INSTALL_SCRIPT")}, + {'P', QLatin1String("PREFIX")}, + {'P', QLatin1String("PROPERTY")}, + {'P', QLatin1String("PRE_INSTALL_SCRIPT")}, + {'P', QLatin1String("PRIVATE_HEADER")}, + {'P', QLatin1String("PROJECT_LABEL")}, + {'P', QLatin1String("PUBLIC_HEADER")}, + {'R', QLatin1String("RESOURCE")}, + {'R', QLatin1String("RULE_LAUNCH_COMPILE")}, + {'R', QLatin1String("RULE_LAUNCH_CUSTOM")}, + {'R', QLatin1String("RULE_LAUNCH_LINK")}, + {'R', QLatin1String("RUNTIME_OUTPUT_DIRECTORY")}, + {'R', QLatin1String("RUNTIME_OUTPUT_NAME")}, + {'S', QLatin1String("SKIP_BUILD_RPATH")}, + {'S', QLatin1String("SOURCES")}, + {'S', QLatin1String("SOVERSION")}, + {'S', QLatin1String("STATIC_LIBRARY_FLAGS")}, + {'S', QLatin1String("SUFFIX")}, + {'T', QLatin1String("TARGET")}, + {'T', QLatin1String("TYPE")}, + {'V', QLatin1String("VERSION")}, + {'V', QLatin1String("VISIBILITY_INLINES_HIDDEN")}, + {'V', QLatin1String("VS_DOTNET_REFERENCES")}, + {'V', QLatin1String("VS_DOTNET_TARGET_FRAMEWORK_VERSION")}, + {'V', QLatin1String("VS_GLOBAL_KEYWORD")}, + {'V', QLatin1String("VS_GLOBAL_PROJECT_TYPES")}, + {'V', QLatin1String("VS_GLOBAL_ROOTNAMESPACE")}, + {'V', QLatin1String("VS_KEYWORD")}, + {'V', QLatin1String("VS_SCC_AUXPATH")}, + {'V', QLatin1String("VS_SCC_LOCALPATH")}, + {'V', QLatin1String("VS_SCC_PROJECTNAME")}, + {'V', QLatin1String("VS_SCC_PROVIDER")}, + {'V', QLatin1String("VS_WINRT_EXTENSIONS")}, + {'V', QLatin1String("VS_WINRT_REFERENCES")}, + {'W', QLatin1String("WIN32_EXECUTABLE")}, + {'A', QLatin1String("ATTACHED_FILES_ON_FAIL")}, + {'A', QLatin1String("ATTACHED_FILES")}, + {'C', QLatin1String("COST")}, + {'D', QLatin1String("DEPENDS")}, + {'E', QLatin1String("ENVIRONMENT")}, + {'F', QLatin1String("FAIL_REGULAR_EXPRESSION")}, + {'L', QLatin1String("LABELS")}, + {'M', QLatin1String("MEASUREMENT")}, + {'P', QLatin1String("PASS_REGULAR_EXPRESSION")}, + {'P', QLatin1String("PROCESSORS")}, + {'R', QLatin1String("REQUIRED_FILES")}, + {'R', QLatin1String("RESOURCE_LOCK")}, + {'R', QLatin1String("RUN_SERIAL")}, + {'S', QLatin1String("SKIP_RETURN_CODE")}, + {'T', QLatin1String("TIMEOUT")}, + {'W', QLatin1String("WILL_FAIL")}, + {'W', QLatin1String("WORKING_DIRECTORY")}, + {'A', QLatin1String("ABSTRACT")}, + {'A', QLatin1String("AUTOUIC_OPTIONS")}, + {'A', QLatin1String("AUTORCC_OPTIONS")}, + {'C', QLatin1String("COMPILE_DEFINITIONS")}, + {'C', QLatin1String("COMPILE_FLAGS")}, + {'E', QLatin1String("EXTERNAL_OBJECT")}, + {'F', QLatin1String("Fortran_FORMAT")}, + {'G', QLatin1String("GENERATED")}, + {'H', QLatin1String("HEADER_FILE_ONLY")}, + {'K', QLatin1String("KEEP_EXTENSION")}, + {'L', QLatin1String("LABELS")}, + // {'L', QLatin1String("LANGUAGE")}, + {'L', QLatin1String("LOCATION")}, + {'M', QLatin1String("MACOSX_PACKAGE_LOCATION")}, + {'O', QLatin1String("OBJECT_DEPENDS")}, + {'O', QLatin1String("OBJECT_OUTPUTS")}, + {'S', QLatin1String("SYMBOLIC")}, + {'W', QLatin1String("WRAP_EXCLUDE")}, + {'A', QLatin1String("ADVANCED")}, + {'H', QLatin1String("HELPSTRING")}, + {'M', QLatin1String("MODIFIED")}, + {'S', QLatin1String("STRINGS")}, + {'T', QLatin1String("TYPE")}, + {'V', QLatin1String("VALUE")}}; + cmake_other = { + {'C', QLatin1String("CMAKE_ARGC")}, + {'C', QLatin1String("CMAKE_ARGV0")}, + {'C', QLatin1String("CMAKE_AR")}, + {'C', QLatin1String("CMAKE_BINARY_DIR")}, + {'C', QLatin1String("CMAKE_BUILD_TOOL")}, + {'C', QLatin1String("CMAKE_CACHEFILE_DIR")}, + {'C', QLatin1String("CMAKE_CACHE_MAJOR_VERSION")}, + {'C', QLatin1String("CMAKE_CACHE_MINOR_VERSION")}, + {'C', QLatin1String("CMAKE_CACHE_PATCH_VERSION")}, + {'C', QLatin1String("CMAKE_CFG_INTDIR")}, + {'C', QLatin1String("CMAKE_COMMAND")}, + {'C', QLatin1String("CMAKE_CROSSCOMPILING")}, + {'C', QLatin1String("CMAKE_CTEST_COMMAND")}, + {'C', QLatin1String("CMAKE_CURRENT_BINARY_DIR")}, + {'C', QLatin1String("CMAKE_CURRENT_LIST_DIR")}, + {'C', QLatin1String("CMAKE_CURRENT_LIST_FILE")}, + {'C', QLatin1String("CMAKE_CURRENT_LIST_LINE")}, + {'C', QLatin1String("CMAKE_CURRENT_SOURCE_DIR")}, + {'C', QLatin1String("CMAKE_DL_LIBS")}, + {'C', QLatin1String("CMAKE_EDIT_COMMAND")}, + {'C', QLatin1String("CMAKE_EXECUTABLE_SUFFIX")}, + {'C', QLatin1String("CMAKE_EXTRA_GENERATOR")}, + {'C', QLatin1String("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")}, + {'C', QLatin1String("CMAKE_GENERATOR")}, + {'C', QLatin1String("CMAKE_GENERATOR_TOOLSET")}, + {'C', QLatin1String("CMAKE_HOME_DIRECTORY")}, + {'C', QLatin1String("CMAKE_IMPORT_LIBRARY_PREFIX")}, + {'C', QLatin1String("CMAKE_IMPORT_LIBRARY_SUFFIX")}, + {'C', QLatin1String("CMAKE_JOB_POOL_COMPILE")}, + {'C', QLatin1String("CMAKE_JOB_POOL_LINK")}, + {'C', QLatin1String("CMAKE_LINK_LIBRARY_SUFFIX")}, + {'C', QLatin1String("CMAKE_MAJOR_VERSION")}, + {'C', QLatin1String("CMAKE_MAKE_PROGRAM")}, + {'C', QLatin1String("CMAKE_MINIMUM_REQUIRED_VERSION")}, + {'C', QLatin1String("CMAKE_MINOR_VERSION")}, + {'C', QLatin1String("CMAKE_PARENT_LIST_FILE")}, + {'C', QLatin1String("CMAKE_PATCH_VERSION")}, + {'C', QLatin1String("CMAKE_PROJECT_NAME")}, + {'C', QLatin1String("CMAKE_RANLIB")}, + {'C', QLatin1String("CMAKE_ROOT")}, + {'C', QLatin1String("CMAKE_SCRIPT_MODE_FILE")}, + {'C', QLatin1String("CMAKE_SHARED_LIBRARY_PREFIX")}, + {'C', QLatin1String("CMAKE_SHARED_LIBRARY_SUFFIX")}, + {'C', QLatin1String("CMAKE_SHARED_MODULE_PREFIX")}, + {'C', QLatin1String("CMAKE_SHARED_MODULE_SUFFIX")}, + {'C', QLatin1String("CMAKE_SIZEOF_VOID_P")}, + {'C', QLatin1String("CMAKE_SKIP_INSTALL_RULES")}, + {'C', QLatin1String("CMAKE_SKIP_RPATH")}, + {'C', QLatin1String("CMAKE_SOURCE_DIR")}, + {'C', QLatin1String("CMAKE_STANDARD_LIBRARIES")}, + {'C', QLatin1String("CMAKE_STATIC_LIBRARY_PREFIX")}, + {'C', QLatin1String("CMAKE_STATIC_LIBRARY_SUFFIX")}, + {'C', QLatin1String("CMAKE_TOOLCHAIN_FILE")}, + {'C', QLatin1String("CMAKE_TWEAK_VERSION")}, + {'C', QLatin1String("CMAKE_VERBOSE_MAKEFILE")}, + {'C', QLatin1String("CMAKE_VERSION")}, + {'C', QLatin1String("CMAKE_VS_DEVENV_COMMAND")}, + {'C', QLatin1String("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION")}, + {'C', QLatin1String("CMAKE_VS_MSBUILD_COMMAND")}, + {'C', QLatin1String("CMAKE_VS_MSDEV_COMMAND")}, + {'C', QLatin1String("CMAKE_VS_PLATFORM_TOOLSET")}, + {'C', QLatin1String("CMAKE_XCODE_PLATFORM_TOOLSET")}, + {'P', QLatin1String("PROJECT_BINARY_DIR")}, + // {'P', QLatin1String("PROJECT_NAME")}, + {'P', QLatin1String("PROJECT_SOURCE_DIR")}, + {'P', QLatin1String("PROJECT_VERSION")}, + {'P', QLatin1String("PROJECT_VERSION_MAJOR")}, + {'P', QLatin1String("PROJECT_VERSION_MINOR")}, + {'P', QLatin1String("PROJECT_VERSION_PATCH")}, + {'P', QLatin1String("PROJECT_VERSION_TWEAK")}, + {'B', QLatin1String("BUILD_SHARED_LIBS")}, + {'C', QLatin1String("CMAKE_ABSOLUTE_DESTINATION_FILES")}, + {'C', QLatin1String("CMAKE_APPBUNDLE_PATH")}, + {'C', QLatin1String("CMAKE_AUTOMOC_RELAXED_MODE")}, + {'C', QLatin1String("CMAKE_BACKWARDS_COMPATIBILITY")}, + {'C', QLatin1String("CMAKE_BUILD_TYPE")}, + {'C', QLatin1String("CMAKE_COLOR_MAKEFILE")}, + {'C', QLatin1String("CMAKE_CONFIGURATION_TYPES")}, + {'C', QLatin1String("CMAKE_DEBUG_TARGET_PROPERTIES")}, + {'C', QLatin1String("CMAKE_ERROR_DEPRECATED")}, + {'C', QLatin1String("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")}, + {'C', QLatin1String("CMAKE_SYSROOT")}, + {'C', QLatin1String("CMAKE_FIND_LIBRARY_PREFIXES")}, + {'C', QLatin1String("CMAKE_FIND_LIBRARY_SUFFIXES")}, + {'C', QLatin1String("CMAKE_FIND_NO_INSTALL_PREFIX")}, + {'C', QLatin1String("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")}, + {'C', QLatin1String("CMAKE_FIND_ROOT_PATH")}, + {'C', QLatin1String("CMAKE_FIND_ROOT_PATH_MODE_INCLUDE")}, + {'C', QLatin1String("CMAKE_FIND_ROOT_PATH_MODE_LIBRARY")}, + {'C', QLatin1String("CMAKE_FIND_ROOT_PATH_MODE_PACKAGE")}, + {'C', QLatin1String("CMAKE_FIND_ROOT_PATH_MODE_PROGRAM")}, + {'C', QLatin1String("CMAKE_FRAMEWORK_PATH")}, + {'C', QLatin1String("CMAKE_IGNORE_PATH")}, + {'C', QLatin1String("CMAKE_INCLUDE_PATH")}, + {'C', QLatin1String("CMAKE_INCLUDE_DIRECTORIES_BEFORE")}, + {'C', QLatin1String("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")}, + {'C', QLatin1String("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME")}, + {'C', QLatin1String("CMAKE_INSTALL_PREFIX")}, + {'C', QLatin1String("CMAKE_LIBRARY_PATH")}, + {'C', QLatin1String("CMAKE_MFC_FLAG")}, + {'C', QLatin1String("CMAKE_MODULE_PATH")}, + {'C', QLatin1String("CMAKE_NOT_USING_CONFIG_FLAGS")}, + {'C', QLatin1String("CMAKE_PREFIX_PATH")}, + {'C', QLatin1String("CMAKE_PROGRAM_PATH")}, + {'C', QLatin1String("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY")}, + {'C', QLatin1String("CMAKE_STAGING_PREFIX")}, + {'C', QLatin1String("CMAKE_SYSTEM_IGNORE_PATH")}, + {'C', QLatin1String("CMAKE_SYSTEM_INCLUDE_PATH")}, + {'C', QLatin1String("CMAKE_SYSTEM_LIBRARY_PATH")}, + {'C', QLatin1String("CMAKE_SYSTEM_PREFIX_PATH")}, + {'C', QLatin1String("CMAKE_SYSTEM_PROGRAM_PATH")}, + {'C', QLatin1String("CMAKE_USER_MAKE_RULES_OVERRIDE")}, + {'C', QLatin1String("CMAKE_WARN_DEPRECATED")}, + {'C', QLatin1String("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")}, + {'A', QLatin1String("APPLE")}, + {'B', QLatin1String("BORLAND")}, + {'C', QLatin1String("CMAKE_CL_64")}, + {'C', QLatin1String("CMAKE_COMPILER_2005")}, + {'C', QLatin1String("CMAKE_HOST_APPLE")}, + {'C', QLatin1String("CMAKE_HOST_SYSTEM_NAME")}, + {'C', QLatin1String("CMAKE_HOST_SYSTEM_PROCESSOR")}, + {'C', QLatin1String("CMAKE_HOST_SYSTEM")}, + {'C', QLatin1String("CMAKE_HOST_SYSTEM_VERSION")}, + {'C', QLatin1String("CMAKE_HOST_UNIX")}, + {'C', QLatin1String("CMAKE_HOST_WIN32")}, + {'C', QLatin1String("CMAKE_LIBRARY_ARCHITECTURE_REGEX")}, + {'C', QLatin1String("CMAKE_LIBRARY_ARCHITECTURE")}, + {'C', QLatin1String("CMAKE_OBJECT_PATH_MAX")}, + {'C', QLatin1String("CMAKE_SYSTEM_NAME")}, + {'C', QLatin1String("CMAKE_SYSTEM_PROCESSOR")}, + {'C', QLatin1String("CMAKE_SYSTEM")}, + {'C', QLatin1String("CMAKE_SYSTEM_VERSION")}, + {'C', QLatin1String("CYGWIN")}, + {'E', QLatin1String("ENV")}, + {'M', QLatin1String("MSVC10")}, + {'M', QLatin1String("MSVC11")}, + {'M', QLatin1String("MSVC12")}, + {'M', QLatin1String("MSVC60")}, + {'M', QLatin1String("MSVC70")}, + {'M', QLatin1String("MSVC71")}, + {'M', QLatin1String("MSVC80")}, + {'M', QLatin1String("MSVC90")}, + {'M', QLatin1String("MSVC_IDE")}, + {'M', QLatin1String("MSVC")}, + {'M', QLatin1String("MSVC_VERSION")}, + {'U', QLatin1String("UNIX")}, + {'W', QLatin1String("WIN32")}, + {'X', QLatin1String("XCODE_VERSION")}, + {'C', QLatin1String("CMAKE_ARCHIVE_OUTPUT_DIRECTORY")}, + {'C', QLatin1String("CMAKE_AUTOMOC_MOC_OPTIONS")}, + {'C', QLatin1String("CMAKE_AUTOMOC")}, + {'C', QLatin1String("CMAKE_AUTORCC")}, + {'C', QLatin1String("CMAKE_AUTORCC_OPTIONS")}, + {'C', QLatin1String("CMAKE_AUTOUIC")}, + {'C', QLatin1String("CMAKE_AUTOUIC_OPTIONS")}, + {'C', QLatin1String("CMAKE_BUILD_WITH_INSTALL_RPATH")}, + {'C', QLatin1String("CMAKE_DEBUG_POSTFIX")}, + {'C', QLatin1String("CMAKE_EXE_LINKER_FLAGS")}, + {'C', QLatin1String("CMAKE_Fortran_FORMAT")}, + {'C', QLatin1String("CMAKE_Fortran_MODULE_DIRECTORY")}, + {'C', QLatin1String("CMAKE_GNUtoMS")}, + {'C', QLatin1String("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")}, + {'C', QLatin1String("CMAKE_INCLUDE_CURRENT_DIR")}, + {'C', QLatin1String("CMAKE_INSTALL_NAME_DIR")}, + {'C', QLatin1String("CMAKE_INSTALL_RPATH")}, + {'C', QLatin1String("CMAKE_INSTALL_RPATH_USE_LINK_PATH")}, + {'C', QLatin1String("CMAKE_LIBRARY_OUTPUT_DIRECTORY")}, + {'C', QLatin1String("CMAKE_LIBRARY_PATH_FLAG")}, + {'C', QLatin1String("CMAKE_LINK_DEF_FILE_FLAG")}, + {'C', QLatin1String("CMAKE_LINK_DEPENDS_NO_SHARED")}, + {'C', QLatin1String("CMAKE_LINK_INTERFACE_LIBRARIES")}, + {'C', QLatin1String("CMAKE_LINK_LIBRARY_FILE_FLAG")}, + {'C', QLatin1String("CMAKE_LINK_LIBRARY_FLAG")}, + {'C', QLatin1String("CMAKE_MACOSX_BUNDLE")}, + {'C', QLatin1String("CMAKE_MACOSX_RPATH")}, + {'C', QLatin1String("CMAKE_MODULE_LINKER_FLAGS")}, + {'C', QLatin1String("CMAKE_NO_BUILTIN_CHRPATH")}, + {'C', QLatin1String("CMAKE_NO_SYSTEM_FROM_IMPORTED")}, + {'C', QLatin1String("CMAKE_OSX_ARCHITECTURES")}, + {'C', QLatin1String("CMAKE_OSX_DEPLOYMENT_TARGET")}, + {'C', QLatin1String("CMAKE_OSX_SYSROOT")}, + {'C', QLatin1String("CMAKE_PDB_OUTPUT_DIRECTORY")}, + {'C', QLatin1String("CMAKE_POSITION_INDEPENDENT_CODE")}, + {'C', QLatin1String("CMAKE_RUNTIME_OUTPUT_DIRECTORY")}, + {'C', QLatin1String("CMAKE_SHARED_LINKER_FLAGS")}, + {'C', QLatin1String("CMAKE_SKIP_BUILD_RPATH")}, + {'C', QLatin1String("CMAKE_SKIP_INSTALL_RPATH")}, + {'C', QLatin1String("CMAKE_STATIC_LINKER_FLAGS")}, + {'C', QLatin1String("CMAKE_TRY_COMPILE_CONFIGURATION")}, + {'C', QLatin1String("CMAKE_USE_RELATIVE_PATHS")}, + {'C', QLatin1String("CMAKE_VISIBILITY_INLINES_HIDDEN")}, + {'C', QLatin1String("CMAKE_WIN32_EXECUTABLE")}, + {'E', QLatin1String("EXECUTABLE_OUTPUT_PATH")}, + {'L', QLatin1String("LIBRARY_OUTPUT_PATH")}, + {'C', QLatin1String("CMAKE_Fortran_MODDIR_DEFAULT")}, + {'C', QLatin1String("CMAKE_Fortran_MODDIR_FLAG")}, + {'C', QLatin1String("CMAKE_Fortran_MODOUT_FLAG")}, + {'C', QLatin1String("CMAKE_INTERNAL_PLATFORM_ABI")}, + {'C', QLatin1String("CPACK_ABSOLUTE_DESTINATION_FILES")}, + {'C', QLatin1String("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")}, + {'C', QLatin1String("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")}, + {'C', QLatin1String("CPACK_INCLUDE_TOPLEVEL_DIRECTORY")}, + {'C', QLatin1String("CPACK_INSTALL_SCRIPT")}, + {'C', QLatin1String("CPACK_PACKAGING_INSTALL_PREFIX")}, + {'C', QLatin1String("CPACK_SET_DESTDIR")}, + {'C', QLatin1String("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")}}; +} + +void loadCMakeData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!cmakeDataInitialized) { + initCMakeData(); + cmakeDataInitialized = true; + } + types = cmake_types; + keywords = cmake_keywords; + builtin = cmake_builtin; + literals = cmake_literals; + other = cmake_other; +} + +/********************************************************/ +/*** MAKE DATA **************************************/ +/********************************************************/ +static bool makeDataInitialized = false; +static QMultiHash make_keywords; +static QMultiHash make_types; +static QMultiHash make_literals; +static QMultiHash make_builtin; +static QMultiHash make_other; +void initMakeData() { + make_keywords = { + {'i', QLatin1String("include")}, {'d', QLatin1String("define")}, + {'e', QLatin1String("else")}, {'e', QLatin1String("endef")}, + {'e', QLatin1String("endif")}, {'e', QLatin1String("export")}, + {'i', QLatin1String("ifn?def")}, {'i', QLatin1String("ifn?eq")}, + {'i', QLatin1String("include")}, {'o', QLatin1String("override")}, + {'p', QLatin1String("private")}, {'s', QLatin1String("sinclude")}, + {'u', QLatin1String("undefine")}, {'u', QLatin1String("unexport")}, + {'v', QLatin1String("vpath")}}; + make_types = { + {'a', QLatin1String("addsuffix")}, {'a', QLatin1String("abspath")}, + {'a', QLatin1String("and")}, {'a', QLatin1String("ar")}, + {'b', QLatin1String("basename")}, {'c', QLatin1String("call")}, + {'d', QLatin1String("dir")}, {'e', QLatin1String("error")}, + {'e', QLatin1String("eval")}, {'f', QLatin1String("file")}, + {'f', QLatin1String("filter")}, {'f', QLatin1String("find")}, + {'f', QLatin1String("findstring")}, {'f', QLatin1String("firstword")}, + {'f', QLatin1String("flavor")}, {'f', QLatin1String("foreach")}, + {'g', QLatin1String("guile")}, {'i', QLatin1String("if")}, + {'i', QLatin1String("info")}, {'i', QLatin1String("install")}, + {'j', QLatin1String("join")}, {'l', QLatin1String("lastword")}, + {'l', QLatin1String("load")}, {'n', QLatin1String("notdir")}, + {'o', QLatin1String("or")}, {'o', QLatin1String("origin")}, + {'p', QLatin1String("patsubst")}, {'r', QLatin1String("ranlib")}, + {'r', QLatin1String("realpath")}, {'r', QLatin1String("rm")}, + {'s', QLatin1String("shell")}, {'s', QLatin1String("sort")}, + {'s', QLatin1String("strip")}, {'s', QLatin1String("subst")}, + {'s', QLatin1String("suffix")}, {'v', QLatin1String("value")}, + {'w', QLatin1String("warning")}, {'w', QLatin1String("wildcard")}, + {'w', QLatin1String("word")}}; + make_literals = { + {'t', QLatin1String("true")}, + {'f', QLatin1String("false")}, + }; + make_builtin = {}; + make_other = { + {'C', QLatin1String("CFLAGS")}, + {'L', QLatin1String("LIBS")}, + {'P', QLatin1String("PREFIX")}, + }; +} + +void loadMakeData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!makeDataInitialized) { + initMakeData(); + makeDataInitialized = true; + } + types = make_types; + keywords = make_keywords; + builtin = make_builtin; + literals = make_literals; + other = make_other; +} + +/********************************************************/ +/*** Forth DATA *************************************/ +/********************************************************/ +static bool forthDataInitialized = false; +static QMultiHash forth_keywords; +static QMultiHash forth_types; +static QMultiHash forth_builtin; +static QMultiHash forth_literals; +static QMultiHash forth_other; +void initForthData() { + forth_keywords = { + {('d'), QLatin1String("disasm")}, + {('d'), QLatin1String("disassembler")}, + {('b'), QLatin1String("base-addr")}, + {('s'), QLatin1String("show-name")}, + {('d'), QLatin1String("default-32bit")}, + {('d'), QLatin1String("default-16bit")}, + {('d'), QLatin1String("default-16bit?")}, + {('c'), QLatin1String("col")}, + {('w'), QLatin1String("w@")}, + {('('), QLatin1String("(D.)")}, + {('M'), QLatin1String("MAXCOUNTED")}, + {('S'), QLatin1String("SPCS")}, + {('S'), QLatin1String("SPCS-MAX")}, + {('m'), QLatin1String("maxstring")}, + {('d'), QLatin1String("dffield:")}, + {('s'), QLatin1String("sffield:")}, + {('f'), QLatin1String("ffield:")}, + {('2'), QLatin1String("2field:")}, + {('f'), QLatin1String("field:")}, + {('c'), QLatin1String("cfield:")}, + {('e'), QLatin1String("end-structure")}, + {('b'), QLatin1String("begin-structure")}, + {('+'), QLatin1String("+field")}, + {('i'), QLatin1String("init-libcc")}, + {('e'), QLatin1String("end-c-library")}, + {('c'), QLatin1String("c-library")}, + {('c'), QLatin1String("c-library-name")}, + {('c'), QLatin1String("c-library-incomplete")}, + {('c'), QLatin1String("clear-libs")}, + {('c'), QLatin1String("c-function")}, + {('c'), QLatin1String("c-function-rt")}, + {('c'), QLatin1String("c-function-ft")}, + {('l'), QLatin1String("link-wrapper-function")}, + {('c'), QLatin1String("compile-wrapper-function1")}, + {('c'), QLatin1String("compile-wrapper-function")}, + {('.'), QLatin1String(".lib-error")}, + {('c'), QLatin1String("c-source-file-execute")}, + {('n'), QLatin1String("notype-execute")}, + {('c'), QLatin1String("c-source-file")}, + {('i'), QLatin1String("init-c-source-file")}, + {('l'), QLatin1String("lib-handle")}, + {('c'), QLatin1String("c-tmp-library-name")}, + {('c'), QLatin1String("c-named-library-name")}, + {('c'), QLatin1String("c-library-name-create")}, + {('c'), QLatin1String("c-library-name-setup")}, + {('o'), QLatin1String("open-wrappers")}, + {('p'), QLatin1String("prepend-dirname")}, + {('l'), QLatin1String("libcc-tmp-dir")}, + {('l'), QLatin1String("libcc-named-dir")}, + {('g'), QLatin1String("gen-filename")}, + {('b'), QLatin1String("basename")}, + {('d'), QLatin1String("dirname")}, + {('s'), QLatin1String("scan-back")}, + {('g'), QLatin1String("gen-wrapper-function")}, + {('w'), QLatin1String("wrapper-function-name")}, + {('g'), QLatin1String("gen-wrapped-stmt")}, + {('g'), QLatin1String("gen-wrapped-types")}, + {('g'), QLatin1String("gen-wrapped-func")}, + {('g'), QLatin1String("gen-wrapped-r")}, + {('g'), QLatin1String("gen-wrapped-d")}, + {('g'), QLatin1String("gen-wrapped-a")}, + {('g'), QLatin1String("gen-wrapped-n")}, + {('g'), QLatin1String("gen-wrapped-void")}, + {('g'), QLatin1String("gen-wrapped-call")}, + {('g'), QLatin1String("gen-par")}, + {('g'), QLatin1String("gen-par-types")}, + {('g'), QLatin1String("gen-par-void")}, + {('g'), QLatin1String("gen-par-func")}, + {('g'), QLatin1String("gen-par-r")}, + {('g'), QLatin1String("gen-par-d")}, + {('g'), QLatin1String("gen-par-a")}, + {('g'), QLatin1String("gen-par-n")}, + {('c'), QLatin1String("count-stacks")}, + {('c'), QLatin1String("count-stacks-types")}, + {('c'), QLatin1String("count-stacks-void")}, + {('c'), QLatin1String("count-stacks-func")}, + {('c'), QLatin1String("count-stacks-r")}, + {('c'), QLatin1String("count-stacks-d")}, + {('c'), QLatin1String("count-stacks-a")}, + {('c'), QLatin1String("count-stacks-n")}, + {('t'), QLatin1String("type-letter")}, + {('p'), QLatin1String("parse-function-types")}, + {('p'), QLatin1String("parse-libcc-type")}, + {('l'), QLatin1String("libcc-types")}, + {('\\'), QLatin1String("\\c")}, + {('s'), QLatin1String("save-c-prefix-line")}, + {('p'), QLatin1String("print-c-prefix-lines")}, + {('p'), QLatin1String("print-c-prefix-line")}, + {('c'), QLatin1String("c-prefix-lines-end")}, + {('c'), QLatin1String("c-prefix-lines")}, + {('c'), QLatin1String("c-prefix%")}, + {('c'), QLatin1String("c-prefix-chars")}, + {('c'), QLatin1String("c-prefix-count")}, + {('a'), QLatin1String("append-l")}, + {('a'), QLatin1String("add-lib")}, + {('c'), QLatin1String("c-libs")}, + {('c'), QLatin1String("c-lib%")}, + {('c'), QLatin1String("c-lib-string")}, + {('l'), QLatin1String("list-map")}, + {('l'), QLatin1String("list-append")}, + {('l'), QLatin1String("list-insert")}, + {('l'), QLatin1String("list%")}, + {('l'), QLatin1String("list-payload")}, + {('l'), QLatin1String("list-next")}, + {('a'), QLatin1String("append")}, + {('s'), QLatin1String("s+")}, + {('f'), QLatin1String("front-char")}, + {('f'), QLatin1String("front-string")}, + {('c'), QLatin1String("const+")}, + {('.'), QLatin1String(".nb")}, + {('r'), QLatin1String("replace-rpath")}, + {('l'), QLatin1String("libcc-path")}, + {('l'), QLatin1String("libcc-named-dir-v")}, + {('l'), QLatin1String("lib-modulename")}, + {('l'), QLatin1String("lib-filename")}, + {('l'), QLatin1String("lib-handle-addr")}, + {('c'), QLatin1String("c-source-file-id")}, + {('c'), QLatin1String("cff%")}, + {('c'), QLatin1String("cff-ptypes")}, + {('c'), QLatin1String("cff-np")}, + {('c'), QLatin1String("cff-rtype")}, + {('c'), QLatin1String("cff-lha")}, + {('c'), QLatin1String("cff-deferred")}, + {('c'), QLatin1String("cff-cfr")}, + {('m'), QLatin1String("mkdir-parents")}, + {('d'), QLatin1String("disasm-gdb")}, + {('a'), QLatin1String("append-extend-string")}, + {('e'), QLatin1String("end-code")}, + {(';'), QLatin1String(";code")}, + {('('), QLatin1String("(;code)")}, + {('c'), QLatin1String("code")}, + {('i'), QLatin1String("init-asm")}, + {('a'), QLatin1String("assembler")}, + {('b'), QLatin1String("break\"")}, + {('('), QLatin1String("(break\")")}, + {('b'), QLatin1String("break:")}, + {('('), QLatin1String("(break:)")}, + {('b'), QLatin1String("break:,")}, + {('d'), QLatin1String("dbg")}, + {('('), QLatin1String("(debug)")}, + {('('), QLatin1String("(_debug)")}, + {('D'), QLatin1String("D-KEY")}, + {('U'), QLatin1String("Unnest")}, + {('N'), QLatin1String("Nesting")}, + {('n'), QLatin1String("nestXT")}, + {('n'), QLatin1String("nestXT-checkSpecial")}, + {('B'), QLatin1String("Body")}, + {('r'), QLatin1String("restore-bp")}, + {('s'), QLatin1String("set-bp")}, + {('D'), QLatin1String("DT")}, + {('B'), QLatin1String("BP")}, + {('b'), QLatin1String("breaker")}, + {('b'), QLatin1String("breaker-size")}, + {('D'), QLatin1String("DebugLoop")}, + {('j'), QLatin1String("jump")}, + {('g'), QLatin1String("get-next")}, + {('d'), QLatin1String("disp-step")}, + {('L'), QLatin1String("Leave-D")}, + {('N'), QLatin1String("NoFine")}, + {('d'), QLatin1String("d.s")}, + {('.'), QLatin1String(".n")}, + {('s'), QLatin1String("scanword")}, + {('r'), QLatin1String("restore-see-flags")}, + {('s'), QLatin1String("save-see-flags")}, + {('d'), QLatin1String("dbg-ip")}, + {('s'), QLatin1String("see-code")}, + {('s'), QLatin1String("see-code-range")}, + {('s'), QLatin1String("see-code-next-inline")}, + {('s'), QLatin1String("simple-see")}, + {('s'), QLatin1String("simple-see-range")}, + {('s'), QLatin1String("simple-see-word")}, + {('p'), QLatin1String("print-backtrace")}, + {('p'), QLatin1String("print-bt-entry")}, + {('b'), QLatin1String("backtrace-return-stack")}, + {('i'), QLatin1String("init-backtrace")}, + {('b'), QLatin1String("backtrace-rs-buffer")}, + {('a'), QLatin1String("adjust-buffer")}, + {('i'), QLatin1String("init-buffer")}, + {('b'), QLatin1String("buffer%")}, + {('b'), QLatin1String("buffer-maxlength")}, + {('b'), QLatin1String("buffer-address")}, + {('b'), QLatin1String("buffer-length")}, + {('b'), QLatin1String("buffer-descriptor")}, + {('c'), QLatin1String("c-extend1")}, + {('c'), QLatin1String("c-lp+!#")}, + {('c'), QLatin1String("c-laddr#")}, + {('c'), QLatin1String("c-f@local#")}, + {('c'), QLatin1String("c-flit")}, + {('c'), QLatin1String("c-@local#")}, + {('c'), QLatin1String("c-branch-lp+!#")}, + {('c'), QLatin1String("c-?branch-lp+!#")}, + {('c'), QLatin1String("c-loop-lp+!#")}, + {('s'), QLatin1String("see")}, + {('n'), QLatin1String("name-see")}, + {('('), QLatin1String("(.immediate)")}, + {('('), QLatin1String("(xt-see-xt)")}, + {('x'), QLatin1String("xt-see")}, + {('s'), QLatin1String("seefield")}, + {('s'), QLatin1String("seecol")}, + {('s'), QLatin1String("seedoes")}, + {('s'), QLatin1String("see-threaded")}, + {('s'), QLatin1String("seedefer")}, + {('s'), QLatin1String("seevalue")}, + {('s'), QLatin1String("seecon")}, + {('s'), QLatin1String("seeuser")}, + {('s'), QLatin1String("seevar")}, + {('s'), QLatin1String("seecode")}, + {('n'), QLatin1String("next-prim")}, + {('n'), QLatin1String("next-head")}, + {('d'), QLatin1String("discode")}, + {('.'), QLatin1String(".defname")}, + {('x'), QLatin1String("xt-see-xt")}, + {('m'), QLatin1String("makepass")}, + {('c'), QLatin1String("c-init")}, + {('a'), QLatin1String("analyse")}, + {('B'), QLatin1String("BranchTo?")}, + {('D'), QLatin1String("DoTable")}, + {('c'), QLatin1String("c-extender")}, + {('C'), QLatin1String("C-Table")}, + {('c'), QLatin1String("c-(compile)")}, + {('c'), QLatin1String("c-does>")}, + {('c'), QLatin1String("c-abort\"")}, + {('c'), QLatin1String("c-exit")}, + {('c'), QLatin1String("c-?do")}, + {('c'), QLatin1String("c-do")}, + {('c'), QLatin1String("c-loop")}, + {('c'), QLatin1String("c-for")}, + {('c'), QLatin1String("c-?branch")}, + {('D'), QLatin1String("DebugBranch")}, + {('c'), QLatin1String("c-branch")}, + {('R'), QLatin1String("RepeatCheck")}, + {('F'), QLatin1String("Forward?")}, + {('c'), QLatin1String("c-string?")}, + {('c'), QLatin1String("c-c\"")}, + {('.'), QLatin1String(".name-without")}, + {('c'), QLatin1String("c-lit+")}, + {('c'), QLatin1String("c-lit")}, + {('c'), QLatin1String("c-callxt")}, + {('c'), QLatin1String("c-call")}, + {('.'), QLatin1String(".word")}, + {('b'), QLatin1String("back?")}, + {('D'), QLatin1String("Debug?")}, + {('D'), QLatin1String("Display?")}, + {('S'), QLatin1String("Scan?")}, + {('D'), QLatin1String("DebugMode")}, + {('D'), QLatin1String("DisplayMode")}, + {('S'), QLatin1String("ScanMode")}, + {('C'), QLatin1String("C-Pass")}, + {('N'), QLatin1String("NoOutput")}, + {('B'), QLatin1String("Branch!")}, + {('T'), QLatin1String("Type!")}, + {(','), QLatin1String(",Branch")}, + {('C'), QLatin1String("CheckWhile")}, + {('M'), QLatin1String("MyBranch")}, + {('C'), QLatin1String("CheckEnd")}, + {('M'), QLatin1String("MoreBranchAddr?")}, + {('B'), QLatin1String("BranchAddr?")}, + {('('), QLatin1String("(BranchAddr?)")}, + {('F'), QLatin1String("FirstBranch")}, + {('M'), QLatin1String("MaxTable")}, + {('B'), QLatin1String("BranchTable")}, + {('S'), QLatin1String("SearchPointer")}, + {('B'), QLatin1String("BranchPointer")}, + {('B'), QLatin1String("Branches")}, + {('C'), QLatin1String("C-Stop")}, + {('L'), QLatin1String("LeaveCode")}, + {('D'), QLatin1String("Disable")}, + {('W'), QLatin1String("WhileCode2")}, + {('A'), QLatin1String("AheadCode")}, + {('E'), QLatin1String("ElseCode")}, + {('U'), QLatin1String("UntilCode")}, + {('A'), QLatin1String("AgainCode")}, + {('R'), QLatin1String("RepeatCode")}, + {('.'), QLatin1String(".struc")}, + {('c'), QLatin1String("c-\\type")}, + {('('), QLatin1String("(.string)")}, + {('.'), QLatin1String(".string")}, + {('c'), QLatin1String("cemit")}, + {('c'), QLatin1String("ctype")}, + {('w'), QLatin1String("warp?")}, + {('('), QLatin1String("(nl)")}, + {('n'), QLatin1String("nl")}, + {('n'), QLatin1String("nlcount")}, + {('u'), QLatin1String("uppercase")}, + {('n'), QLatin1String("nlflag")}, + {('l'), QLatin1String("level-")}, + {('l'), QLatin1String("level+")}, + {('F'), QLatin1String("Format")}, + {('L'), QLatin1String("Level")}, + {('Y'), QLatin1String("YPos")}, + {('X'), QLatin1String("XPos")}, + {('C'), QLatin1String("C-Clearline")}, + {('C'), QLatin1String("C-Highlight")}, + {('C'), QLatin1String("C-Formated")}, + {('C'), QLatin1String("C-Output")}, + {('.'), QLatin1String(".\"")}, + {('s'), QLatin1String("s\"")}, + {('\\'), QLatin1String("\\\"-parse")}, + {('\\'), QLatin1String("\\-escape")}, + {('\\'), QLatin1String("\\-escape-table")}, + {('p'), QLatin1String("parse-num")}, + {('p'), QLatin1String("parse-num-x")}, + {('c'), QLatin1String("char/")}, + {('e'), QLatin1String("ekey?")}, + {('e'), QLatin1String("ekey>fkey")}, + {('e'), QLatin1String("ekey>char")}, + {('e'), QLatin1String("ekey")}, + {('c'), QLatin1String("clear-ekey-buffer")}, + {('e'), QLatin1String("esc-sequence")}, + {('e'), QLatin1String("esc-prefix")}, + {('e'), QLatin1String("ekey-buffered")}, + {('e'), QLatin1String("ekey-buffer")}, + {('e'), QLatin1String("esc-sequences")}, + {('u'), QLatin1String("unkeys")}, + {('u'), QLatin1String("unkey")}, + {('c'), QLatin1String("char-append-buffer")}, + {('k'), QLatin1String("key-buffered")}, + {('k'), QLatin1String("key-buffer")}, + {('s'), QLatin1String("s-k12")}, + {('s'), QLatin1String("s-k11")}, + {('s'), QLatin1String("s-k10")}, + {('s'), QLatin1String("s-k9")}, + {('s'), QLatin1String("s-k8")}, + {('s'), QLatin1String("s-k7")}, + {('s'), QLatin1String("s-k6")}, + {('s'), QLatin1String("s-k5")}, + {('s'), QLatin1String("s-k4")}, + {('s'), QLatin1String("s-k3")}, + {('s'), QLatin1String("s-k2")}, + {('s'), QLatin1String("s-k1")}, + {('k'), QLatin1String("k12")}, + {('k'), QLatin1String("k11")}, + {('k'), QLatin1String("k10")}, + {('k'), QLatin1String("k9")}, + {('k'), QLatin1String("k8")}, + {('k'), QLatin1String("k7")}, + {('k'), QLatin1String("k6")}, + {('k'), QLatin1String("k5")}, + {('k'), QLatin1String("k4")}, + {('k'), QLatin1String("k3")}, + {('k'), QLatin1String("k2")}, + {('k'), QLatin1String("k1")}, + {('k'), QLatin1String("k-f12")}, + {('k'), QLatin1String("k-f11")}, + {('k'), QLatin1String("k-f10")}, + {('k'), QLatin1String("k-f9")}, + {('k'), QLatin1String("k-f8")}, + {('k'), QLatin1String("k-f7")}, + {('k'), QLatin1String("k-f6")}, + {('k'), QLatin1String("k-f5")}, + {('k'), QLatin1String("k-f4")}, + {('k'), QLatin1String("k-f3")}, + {('k'), QLatin1String("k-f2")}, + {('k'), QLatin1String("k-f1")}, + {('k'), QLatin1String("k-delete")}, + {('k'), QLatin1String("k-insert")}, + {('k'), QLatin1String("k-next")}, + {('k'), QLatin1String("k-prior")}, + {('k'), QLatin1String("k-end")}, + {('k'), QLatin1String("k-home")}, + {('k'), QLatin1String("k-down")}, + {('k'), QLatin1String("k-up")}, + {('k'), QLatin1String("k-right")}, + {('k'), QLatin1String("k-left")}, + {('k'), QLatin1String("k-alt-mask")}, + {('k'), QLatin1String("k-ctrl-mask")}, + {('k'), QLatin1String("k-shift-mask")}, + {('k'), QLatin1String("keycode")}, + {('t'), QLatin1String("table")}, + {('t'), QLatin1String("tablesearch-map")}, + {('t'), QLatin1String("table-find")}, + {('s'), QLatin1String("savesystem")}, + {('d'), QLatin1String("dump-fi")}, + {('u'), QLatin1String("update-image-included-files")}, + {('d'), QLatin1String("delete-prefix")}, + {('s'), QLatin1String("save-mem-dict")}, + {('<'), QLatin1String("")}, + {('('), QLatin1String("(compilation>1)")}, + {('<'), QLatin1String("")}, + {('('), QLatin1String("(interpretation>1)")}, + {('f'), QLatin1String("fix-does-code")}, + {('c'), QLatin1String("create-interpret/compile")}, + {('n'), QLatin1String("no-interpretation-does-code")}, + {('n'), QLatin1String("no-compilation-does-code")}, + {('b'), QLatin1String("bye")}, + {('b'), QLatin1String("block-included")}, + {('-'), QLatin1String("-->")}, + {('+'), QLatin1String("+thru")}, + {('+'), QLatin1String("+load")}, + {('t'), QLatin1String("thru")}, + {('l'), QLatin1String("load")}, + {('b'), QLatin1String("block-input")}, + {('l'), QLatin1String("list")}, + {('u'), QLatin1String("updated?")}, + {('s'), QLatin1String("scr")}, + {('b'), QLatin1String("buffer")}, + {('b'), QLatin1String("block")}, + {('g'), QLatin1String("get-buffer")}, + {('f'), QLatin1String("flush")}, + {('e'), QLatin1String("empty-buffers")}, + {('s'), QLatin1String("save-buffers")}, + {('e'), QLatin1String("empty-buffer")}, + {('s'), QLatin1String("save-buffer")}, + {('u'), QLatin1String("update")}, + {('b'), QLatin1String("block-position")}, + {('g'), QLatin1String("get-block-fid")}, + {('u'), QLatin1String("use")}, + {('o'), QLatin1String("open-blocks")}, + {('f'), QLatin1String("flush-blocks")}, + {('b'), QLatin1String("block-cold")}, + {('o'), QLatin1String("offset")}, + {('b'), QLatin1String("block-offset")}, + {('b'), QLatin1String("block-fid")}, + {('b'), QLatin1String("block-limit")}, + {('b'), QLatin1String("buffers")}, + {('l'), QLatin1String("last-block")}, + {('b'), QLatin1String("block-buffers")}, + {('b'), QLatin1String("buffer-struct")}, + {('n'), QLatin1String("next-buffer")}, + {('b'), QLatin1String("block-buffer")}, + {('b'), QLatin1String("buffer-dirty")}, + {('b'), QLatin1String("buffer-fid")}, + {('b'), QLatin1String("buffer-block")}, + {(')'), QLatin1String(")")}, + {('('), QLatin1String("(end-assert)")}, + {('a'), QLatin1String("assert(")}, + {('a'), QLatin1String("assert3(")}, + {('a'), QLatin1String("assert2(")}, + {('a'), QLatin1String("assert1(")}, + {('a'), QLatin1String("assert0(")}, + {('a'), QLatin1String("assertn")}, + {('a'), QLatin1String("assert-level")}, + {('~'), QLatin1String("~~")}, + {('.'), QLatin1String(".debugline-stderr")}, + {('('), QLatin1String("(.debugline)")}, + {('.'), QLatin1String(".debugline")}, + {('p'), QLatin1String("printdebugdata")}, + {('.'), QLatin1String(".sourcepos")}, + {('c'), QLatin1String("compile-sourcepos")}, + {('c'), QLatin1String("current-sourcepos")}, + {('s'), QLatin1String("str>loadfilename#")}, + {('l'), QLatin1String("loadfilename#>str")}, + {('v'), QLatin1String("vt100-decode")}, + {('t'), QLatin1String("tcode")}, + {('t'), QLatin1String("trans:")}, + {('t'), QLatin1String("transcode")}, + {('t'), QLatin1String("translate")}, + {('h'), QLatin1String("history-cold")}, + {('g'), QLatin1String("get-history")}, + {('x'), QLatin1String("xchar-history")}, + {('x'), QLatin1String("xtab-expand")}, + {('i'), QLatin1String("insert")}, + {('x'), QLatin1String("xkill-expand")}, + {('('), QLatin1String("(xenter)")}, + {('x'), QLatin1String("xclear-tib")}, + {('x'), QLatin1String("xclear-line")}, + {('x'), QLatin1String("xend-pos")}, + {('x'), QLatin1String("xfirst-pos")}, + {('x'), QLatin1String("xeof")}, + {('<'), QLatin1String("")}, + {('?'), QLatin1String("?xdel")}, + {('('), QLatin1String("(xdel)")}, + {('x'), QLatin1String("xforw")}, + {('x'), QLatin1String("xback")}, + {('('), QLatin1String("(xins)")}, + {('<'), QLatin1String("")}, + {('x'), QLatin1String("xretype")}, + {('.'), QLatin1String(".all")}, + {('.'), QLatin1String(".rest")}, + {('x'), QLatin1String("xback-restore")}, + {('x'), QLatin1String("xcur-correct")}, + {('a'), QLatin1String("at-deltaxy")}, + {('#'), QLatin1String("#esc")}, + {('k'), QLatin1String("kill-prefix")}, + {('t'), QLatin1String("tib-full?")}, + {('s'), QLatin1String("search-prefix")}, + {('p'), QLatin1String("prefix-string")}, + {('p'), QLatin1String("prefix-off")}, + {('s'), QLatin1String("search-voc")}, + {('w'), QLatin1String("word-lex")}, + {('c'), QLatin1String("capscomp")}, + {('s'), QLatin1String("sgn")}, + {('p'), QLatin1String("prefix-found")}, + {('e'), QLatin1String("extract-word")}, + {('('), QLatin1String("(enter)")}, + {('p'), QLatin1String("prev-line")}, + {('f'), QLatin1String("find-prev-line")}, + {('n'), QLatin1String("next-line")}, + {('g'), QLatin1String("get-line")}, + {('h'), QLatin1String("hist-setpos")}, + {('h'), QLatin1String("hist-pos")}, + {('c'), QLatin1String("clear-line")}, + {('l'), QLatin1String("linew-off")}, + {('s'), QLatin1String("screenw")}, + {('l'), QLatin1String("linew")}, + {('c'), QLatin1String("cur-correct")}, + {('b'), QLatin1String("back-restore")}, + {('h'), QLatin1String("history-file")}, + {('f'), QLatin1String("force-open")}, + {('e'), QLatin1String("end^")}, + {('b'), QLatin1String("backward^")}, + {('f'), QLatin1String("forward^")}, + {('h'), QLatin1String("history")}, + {('b'), QLatin1String("bindkey")}, + {('>'), QLatin1String(">string")}, + {('c'), QLatin1String("ctrl")}, + {('c'), QLatin1String("ctrl-i")}, + {('u'), QLatin1String("utf-8-cold")}, + {('s'), QLatin1String("set-encoding-utf-8")}, + {('u'), QLatin1String("u8width")}, + {('-'), QLatin1String("-u8trailing-garbage")}, + {('u'), QLatin1String("u8addrlen")}, + {('u'), QLatin1String("u8!+?")}, + {('u'), QLatin1String("u8@")}, + {('u'), QLatin1String("u8\\string-")}, + {('+'), QLatin1String("+u8/string")}, + {('u'), QLatin1String("u8emit")}, + {('u'), QLatin1String("u8key")}, + {('c'), QLatin1String("check-xy")}, + {('u'), QLatin1String("u8<<")}, + {('u'), QLatin1String("u8>>")}, + {('u'), QLatin1String("u8!+")}, + {('u'), QLatin1String("u8@+")}, + {('u'), QLatin1String("u8len")}, + {('m'), QLatin1String("max-single-byte")}, + {('U'), QLatin1String("UTF-8-err")}, + {('O'), QLatin1String("O-PNT@")}, + {('O'), QLatin1String("O-DEINIT")}, + {('O'), QLatin1String("O-INIT")}, + {('T'), QLatin1String("TypeXT")}, + {('E'), QLatin1String("EmitXT")}, + {('O'), QLatin1String("O-EMIT")}, + {('O'), QLatin1String("O-TYPE")}, + {('O'), QLatin1String("O-PNT")}, + {('O'), QLatin1String("O-Buffer")}, + {('p'), QLatin1String("page")}, + {('a'), QLatin1String("at-xy")}, + {('E'), QLatin1String("ESC[")}, + {(';'), QLatin1String(";pn")}, + {('p'), QLatin1String("pn")}, + {('W'), QLatin1String("WordInfo")}, + {('I'), QLatin1String("InfoTable")}, + {('C'), QLatin1String("Com#")}, + {('S'), QLatin1String("Str#")}, + {('A'), QLatin1String("Ali#")}, + {('U'), QLatin1String("Use#")}, + {('C'), QLatin1String("Col#")}, + {('D'), QLatin1String("Def#")}, + {('D'), QLatin1String("Doe#")}, + {('V'), QLatin1String("Val#")}, + {('V'), QLatin1String("Var#")}, + {('C'), QLatin1String("Con#")}, + {('P'), QLatin1String("Pri#")}, + {('p'), QLatin1String("prim?")}, + {('x'), QLatin1String("xtprim?")}, + {('c'), QLatin1String("colon?")}, + {('d'), QLatin1String("defered?")}, + {('d'), QLatin1String("does?")}, + {('u'), QLatin1String("user?")}, + {('c'), QLatin1String("con?")}, + {('v'), QLatin1String("var?")}, + {('a'), QLatin1String("alias?")}, + {('>'), QLatin1String(">head")}, + {('>'), QLatin1String(">name")}, + {('t'), QLatin1String("threaded>name")}, + {('l'), QLatin1String("look")}, + {('p'), QLatin1String("prim>name")}, + {('P'), QLatin1String("PrimStart")}, + {('t'), QLatin1String("threaded>xt")}, + {('s'), QLatin1String("search-name")}, + {('x'), QLatin1String("xt>threaded")}, + {('b'), QLatin1String("base-execute")}, + {('i'), QLatin1String("infile-execute")}, + {('o'), QLatin1String("outfile-execute")}, + {('l'), QLatin1String("l@")}, + {('w'), QLatin1String("w@")}, + {('/'), QLatin1String("/l")}, + {('/'), QLatin1String("/w")}, + {('t'), QLatin1String("typewhite")}, + {('w'), QLatin1String("what's")}, + {('a'), QLatin1String("action-of")}, + {('f'), QLatin1String("f.s")}, + {('f'), QLatin1String("f.rdp")}, + {('f'), QLatin1String("f>str-rdp")}, + {('f'), QLatin1String("f>buf-rdp")}, + {('f'), QLatin1String("f>buf-rdp-try")}, + {('p'), QLatin1String("push-right")}, + {(']'), QLatin1String("]]")}, + {('p'), QLatin1String("postponer1")}, + {('['), QLatin1String("[[")}, + {('c'), QLatin1String("compile-compile-2literal")}, + {('c'), QLatin1String("compile-2literal")}, + {('c'), QLatin1String("compile-compile-literal")}, + {('c'), QLatin1String("compile-literal")}, + {('s'), QLatin1String("slurp-fid")}, + {('s'), QLatin1String("slurp-file")}, + {('c'), QLatin1String("const-does>")}, + {('('), QLatin1String("(const-does>)")}, + {('c'), QLatin1String("compile-fliterals")}, + {('c'), QLatin1String("compile-literals")}, + {('i'), QLatin1String("in-return-stack?")}, + {(']'), QLatin1String("]L")}, + {('s'), QLatin1String("sh")}, + {('s'), QLatin1String("system")}, + {('$'), QLatin1String("$?")}, + {('d'), QLatin1String("dmax")}, + {('d'), QLatin1String("dmin")}, + {('?'), QLatin1String("?CSP")}, + {('!'), QLatin1String("!CSP")}, + {('C'), QLatin1String("CSP")}, + {('n'), QLatin1String("needs")}, + {('l'), QLatin1String("locals|")}, + {('T'), QLatin1String("TO")}, + {('d'), QLatin1String("definer!")}, + {('>'), QLatin1String(">definer")}, + {('('), QLatin1String("(local)")}, + {('('), QLatin1String("(exit-like)")}, + {('('), QLatin1String("(until-like)")}, + {('('), QLatin1String("(again-like)")}, + {('('), QLatin1String("(begin-like)")}, + {('('), QLatin1String("(then-like)")}, + {('l'), QLatin1String("locals-;-hook")}, + {('l'), QLatin1String("locals-:-hook")}, + {('e'), QLatin1String("endscope")}, + {('a'), QLatin1String("adjust-locals-list")}, + {('s'), QLatin1String("scope")}, + {('{'), QLatin1String("{")}, + {('o'), QLatin1String("old-dpp")}, + {('n'), QLatin1String("new-locals-wl")}, + {('n'), QLatin1String("new-locals-map")}, + {('n'), QLatin1String("new-locals-reveal")}, + {('n'), QLatin1String("new-locals-find")}, + {('s'), QLatin1String("some-wlocal")}, + {('s'), QLatin1String("some-flocal")}, + {('s'), QLatin1String("some-dlocal")}, + {('s'), QLatin1String("some-clocal")}, + {('l'), QLatin1String("locals-types")}, + {('l'), QLatin1String("lp-offset,")}, + {('l'), QLatin1String("lp-offset")}, + {('c'), QLatin1String("create-local")}, + {('c'), QLatin1String("compile-pushlocal-c")}, + {('c'), QLatin1String("compile-pushlocal-d")}, + {('c'), QLatin1String("compile-pushlocal-f")}, + {('c'), QLatin1String("check-begin")}, + {('s'), QLatin1String("set-locals-size-list")}, + {('l'), QLatin1String("list-size")}, + {('s'), QLatin1String("sub-list?")}, + {('c'), QLatin1String("common-list")}, + {('c'), QLatin1String("compile-pushlocal-w")}, + {('a'), QLatin1String("alignlp-f")}, + {('a'), QLatin1String("alignlp-w")}, + {('l'), QLatin1String("locals-dp")}, + {('l'), QLatin1String("locals-buffer")}, + {('l'), QLatin1String("locals")}, + {('a'), QLatin1String("adjust-locals-size")}, + {('c'), QLatin1String("compile-lp+!")}, + {('c'), QLatin1String("compile-f@local")}, + {('c'), QLatin1String("compile-@local")}, + {('F'), QLatin1String("FMOD")}, + {('F'), QLatin1String("FTRUNC")}, + {('f'), QLatin1String("f~")}, + {('f'), QLatin1String("f~rel")}, + {('f'), QLatin1String("f~abs")}, + {('1'), QLatin1String("1/f")}, + {('f'), QLatin1String("f2/")}, + {('f'), QLatin1String("f2*")}, + {('p'), QLatin1String("pi")}, + {('f'), QLatin1String("fvariable")}, + {('s'), QLatin1String("sfnumber")}, + {('f'), QLatin1String("fs.")}, + {('f'), QLatin1String("fe.")}, + {('f'), QLatin1String("f.")}, + {('f'), QLatin1String("f$")}, + {('-'), QLatin1String("-zeros")}, + {('z'), QLatin1String("zeros")}, + {('s'), QLatin1String("scratch")}, + {('s'), QLatin1String("set-precision")}, + {('p'), QLatin1String("precision")}, + {('F'), QLatin1String("FLiteral")}, + {('f'), QLatin1String("fdepth")}, + {('f'), QLatin1String("fconstant")}, + {('f'), QLatin1String("f,")}, + {('d'), QLatin1String("dfloat+")}, + {('s'), QLatin1String("sfloat+")}, + {('d'), QLatin1String("dfalign")}, + {('s'), QLatin1String("sfalign")}, + {('.'), QLatin1String(".words")}, + {('h'), QLatin1String("hash-cold")}, + {('m'), QLatin1String("make-hash")}, + {('('), QLatin1String("(hashsearch-map)")}, + {('h'), QLatin1String("hashdouble")}, + {('('), QLatin1String("(rehash)")}, + {('r'), QLatin1String("rehashall")}, + {('c'), QLatin1String("clearhash")}, + {('a'), QLatin1String("addall")}, + {('i'), QLatin1String("inithash")}, + {('h'), QLatin1String("hash-reveal")}, + {('('), QLatin1String("(reveal")}, + {('l'), QLatin1String("lastlink!")}, + {('h'), QLatin1String("hash-find")}, + {('b'), QLatin1String("bucket")}, + {('N'), QLatin1String("NewFix")}, + {('D'), QLatin1String("DelFix")}, + {('h'), QLatin1String("hash-alloc")}, + {('h'), QLatin1String("hashsearch-map")}, + {('H'), QLatin1String("HashTable")}, + {('H'), QLatin1String("HashPop")}, + {('H'), QLatin1String("HashIndex")}, + {('H'), QLatin1String("HashPointer")}, + {('r'), QLatin1String("revealed")}, + {('i'), QLatin1String("insRule")}, + {('h'), QLatin1String("hash")}, + {('H'), QLatin1String("Hashlen")}, + {('h'), QLatin1String("hashbits")}, + {('r'), QLatin1String("reserve-mem")}, + {('m'), QLatin1String("marker")}, + {('m'), QLatin1String("marker!")}, + {('m'), QLatin1String("marker,")}, + {('i'), QLatin1String("included-files-mark")}, + {('e'), QLatin1String("expect")}, + {('s'), QLatin1String("span")}, + {('s'), QLatin1String("search")}, + {('b'), QLatin1String("blank")}, + {('e'), QLatin1String("erase")}, + {('c'), QLatin1String("convert")}, + {('['), QLatin1String("[compile]")}, + {('C'), QLatin1String("C\"")}, + {('e'), QLatin1String("endcase")}, + {('e'), QLatin1String("endof")}, + {('o'), QLatin1String("of")}, + {('c'), QLatin1String("case")}, + {('m'), QLatin1String("m*/")}, + {('d'), QLatin1String("d>s")}, + {('.'), QLatin1String(".(")}, + {('b'), QLatin1String("broken-pipe-error")}, + {('e'), QLatin1String("exception")}, + {('n'), QLatin1String("next-exception")}, + {('e'), QLatin1String("errstring")}, + {('l'), QLatin1String("linked")}, + {('i'), QLatin1String("include-ffi.h-string")}, + {('l'), QLatin1String("libffi-present")}, + {('f'), QLatin1String("ffcall-present")}, + {('l'), QLatin1String("libtool-flags")}, + {('l'), QLatin1String("libtool-cc")}, + {('l'), QLatin1String("libtool-command")}, + {('h'), QLatin1String("has?")}, + {('$'), QLatin1String("$has?")}, + {('e'), QLatin1String("e?")}, + {('e'), QLatin1String("environment?")}, + {('e'), QLatin1String("environment-wordlist")}, + {('e'), QLatin1String("environment")}, + {('v'), QLatin1String("vocs")}, + {('o'), QLatin1String("order")}, + {('.'), QLatin1String(".voc")}, + {('.'), QLatin1String(".name")}, + {('.'), QLatin1String(".id")}, + {('i'), QLatin1String("id.")}, + {('s'), QLatin1String("seal")}, + {('s'), QLatin1String("set-order")}, + {('g'), QLatin1String("get-order")}, + {('i'), QLatin1String("init-vp")}, + {('u'), QLatin1String("update-image-order")}, + {('O'), QLatin1String("Only")}, + {('R'), QLatin1String("Root")}, + {('F'), QLatin1String("Forth")}, + {('v'), QLatin1String("vocsearch")}, + {('('), QLatin1String("(localsvocfind)")}, + {('l'), QLatin1String("locals-wordlist")}, + {('('), QLatin1String("(vocfind)")}, + {('p'), QLatin1String("previous")}, + {('a'), QLatin1String("also")}, + {('>'), QLatin1String(">order")}, + {('c'), QLatin1String("check-maxvp")}, + {('V'), QLatin1String("Vocabulary")}, + {('w'), QLatin1String("wordlist")}, + {('m'), QLatin1String("mappedwordlist")}, + {('s'), QLatin1String("slowvoc")}, + {('d'), QLatin1String("definitions")}, + {('v'), QLatin1String("vp!")}, + {('s'), QLatin1String("set-current")}, + {('g'), QLatin1String("get-current")}, + {('v'), QLatin1String("vp")}, + {('m'), QLatin1String("maxvp-limit")}, + {('m'), QLatin1String("maxvp")}, + {('%'), QLatin1String("%alloc")}, + {('%'), QLatin1String("%allocate")}, + {('%'), QLatin1String("%allot")}, + {('%'), QLatin1String("%align")}, + {('%'), QLatin1String("%size")}, + {('%'), QLatin1String("%alignment")}, + {('d'), QLatin1String("double%")}, + {('s'), QLatin1String("sfloat%")}, + {('d'), QLatin1String("dfloat%")}, + {('f'), QLatin1String("float%")}, + {('c'), QLatin1String("char%")}, + {('c'), QLatin1String("cell%")}, + {('s'), QLatin1String("struct")}, + {('e'), QLatin1String("end-struct")}, + {('f'), QLatin1String("field")}, + {('c'), QLatin1String("create-field")}, + {('f'), QLatin1String("field,")}, + {('d'), QLatin1String("dozerofield")}, + {('n'), QLatin1String("nalign")}, + {('n'), QLatin1String("naligned")}, + {('e'), QLatin1String("endtry-iferror")}, + {('e'), QLatin1String("endtry")}, + {('r'), QLatin1String("restore")}, + {('i'), QLatin1String("iferror")}, + {('h'), QLatin1String("handler-intro,")}, + {('('), QLatin1String("(endtry)")}, + {('t'), QLatin1String("try")}, + {('('), QLatin1String("(try)")}, + {('n'), QLatin1String("nothrow")}, + {('f'), QLatin1String("first-throw")}, + {('s'), QLatin1String("store-backtrace")}, + {('d'), QLatin1String("dodoes:")}, + {('d'), QLatin1String("dofield:")}, + {('d'), QLatin1String("dodefer:")}, + {('d'), QLatin1String("douser:")}, + {('d'), QLatin1String("dovar:")}, + {('d'), QLatin1String("docol:")}, + {('d'), QLatin1String("dovalue:")}, + {('d'), QLatin1String("docon:")}, + {('v'), QLatin1String("vlist")}, + {('w'), QLatin1String("words")}, + {('w'), QLatin1String("wordlist-words")}, + {('c'), QLatin1String("cols")}, + {('r'), QLatin1String("rows")}, + {('?'), QLatin1String("?")}, + {('d'), QLatin1String("dump")}, + {('.'), QLatin1String(".line")}, + {('.'), QLatin1String(".chars")}, + {('.'), QLatin1String(".4")}, + {('/'), QLatin1String("/dump")}, + {('.'), QLatin1String(".s")}, + {('m'), QLatin1String("maxdepth-.s")}, + {('['), QLatin1String("[WHILE]")}, + {('['), QLatin1String("[AGAIN]")}, + {('['), QLatin1String("[REPEAT]")}, + {('['), QLatin1String("[UNTIL]")}, + {('['), QLatin1String("[BEGIN]")}, + {('['), QLatin1String("[I]")}, + {('['), QLatin1String("[NEXT]")}, + {('['), QLatin1String("[FOR]")}, + {('['), QLatin1String("[LOOP]")}, + {('['), QLatin1String("[+LOOP]")}, + {('['), QLatin1String("[?DO]")}, + {('['), QLatin1String("[DO]")}, + {('('), QLatin1String("(i)")}, + {('['), QLatin1String("[ENDIF]")}, + {('['), QLatin1String("[THEN]")}, + {('['), QLatin1String("[ELSE]")}, + {('['), QLatin1String("[IFUNDEF]")}, + {('['), QLatin1String("[IFDEF]")}, + {('['), QLatin1String("[IF]")}, + {('['), QLatin1String("[undefined]")}, + {('d'), QLatin1String("defined")}, + {('['), QLatin1String("[defined]")}, + {('?'), QLatin1String("?if")}, + {('['), QLatin1String("[struct]-voc")}, + {('['), QLatin1String("[struct]-search")}, + {('s'), QLatin1String("scanIF")}, + {('>'), QLatin1String(">exec")}, + {('d'), QLatin1String("dummy")}, + {('c'), QLatin1String("countif")}, + {('.'), QLatin1String(".\"")}, + {('S'), QLatin1String("S\"")}, + {('a'), QLatin1String("abort\"")}, + {('S'), QLatin1String("SLiteral")}, + {('C'), QLatin1String("CLiteral")}, + {('?'), QLatin1String("?EXIT")}, + {('E'), QLatin1String("EXIT")}, + {('e'), QLatin1String("exit-like")}, + {('N'), QLatin1String("NEXT")}, + {('S'), QLatin1String("S+LOOP")}, + {('-'), QLatin1String("-LOOP")}, + {('+'), QLatin1String("+LOOP")}, + {('L'), QLatin1String("LOOP")}, + {('l'), QLatin1String("loop-like")}, + {('F'), QLatin1String("FOR")}, + {('U'), QLatin1String("U-DO")}, + {('-'), QLatin1String("-DO")}, + {('U'), QLatin1String("U+DO")}, + {('+'), QLatin1String("+DO")}, + {('?'), QLatin1String("?DO")}, + {('?'), QLatin1String("?do-like")}, + {('D'), QLatin1String("DO")}, + {('?'), QLatin1String("?LEAVE")}, + {('L'), QLatin1String("LEAVE")}, + {('D'), QLatin1String("DONE")}, + {('l'), QLatin1String("leave>")}, + {('>'), QLatin1String(">leave")}, + {('c'), QLatin1String("clear-leave-stack")}, + {('l'), QLatin1String("leave-sp")}, + {('l'), QLatin1String("leave-stack")}, + {('l'), QLatin1String("leave-stack-size")}, + {('R'), QLatin1String("REPEAT")}, + {('W'), QLatin1String("WHILE")}, + {('U'), QLatin1String("UNTIL")}, + {('u'), QLatin1String("until-like")}, + {('A'), QLatin1String("AGAIN")}, + {('a'), QLatin1String("again-like")}, + {('B'), QLatin1String("BEGIN")}, + {('b'), QLatin1String("begin-like")}, + {('E'), QLatin1String("ELSE")}, + {('E'), QLatin1String("ENDIF")}, + {('T'), QLatin1String("THEN")}, + {('c'), QLatin1String("cs>addr")}, + {('t'), QLatin1String("then-like")}, + {('?'), QLatin1String("?DUP-0=-IF")}, + {('?'), QLatin1String("?DUP-IF")}, + {('I'), QLatin1String("IF")}, + {('A'), QLatin1String("AHEAD")}, + {('Y'), QLatin1String("YET")}, + {('B'), QLatin1String("BUT")}, + {('<'), QLatin1String("'), QLatin1String(">resolve")}, + {('>'), QLatin1String(">mark")}, + {('s'), QLatin1String("sys?")}, + {('?'), QLatin1String("?struc")}, + {('o'), QLatin1String("other-control-flow")}, + {('c'), QLatin1String("cs-push-orig")}, + {('c'), QLatin1String("cs-push-part")}, + {('C'), QLatin1String("CS-ROLL")}, + {('C'), QLatin1String("CS-PICK")}, + {('c'), QLatin1String("cs-item-size")}, + {('c'), QLatin1String("cs-item?")}, + {('n'), QLatin1String("non-orig?")}, + {('s'), QLatin1String("scope?")}, + {('d'), QLatin1String("do-dest?")}, + {('d'), QLatin1String("dest?")}, + {('o'), QLatin1String("orig?")}, + {('d'), QLatin1String("def?")}, + {('s'), QLatin1String("scopestart")}, + {('d'), QLatin1String("do-dest")}, + {('d'), QLatin1String("dest")}, + {('d'), QLatin1String("dead-orig")}, + {('l'), QLatin1String("live-orig")}, + {('A'), QLatin1String("ASSUME-LIVE")}, + {('U'), QLatin1String("UNREACHABLE")}, + {('b'), QLatin1String("backedge-locals")}, + {('d'), QLatin1String("dead-code")}, + {('l'), QLatin1String("locals-list")}, + {('.'), QLatin1String(".included")}, + {('.'), QLatin1String(".strings")}, + {('r'), QLatin1String("require")}, + {('i'), QLatin1String("include")}, + {('r'), QLatin1String("required")}, + {('i'), QLatin1String("included")}, + {('i'), QLatin1String("included1")}, + {('a'), QLatin1String("add-included-file")}, + {('i'), QLatin1String("included?")}, + {('i'), QLatin1String("init-included-files")}, + {('s'), QLatin1String("sourceline#")}, + {('s'), QLatin1String("sourcefilename")}, + {('i'), QLatin1String("image-included-files")}, + {('i'), QLatin1String("included-files")}, + {('o'), QLatin1String("open-fpath-file")}, + {('o'), QLatin1String("open-path-file")}, + {('c'), QLatin1String("check-path")}, + {('o'), QLatin1String("open-ofile")}, + {('r'), QLatin1String("reworkdir")}, + {('c'), QLatin1String("compact-filename")}, + {('s'), QLatin1String("skip-..-prefixes")}, + {('p'), QLatin1String("preserve-root")}, + {('d'), QLatin1String("del-./s")}, + {('d'), QLatin1String("del-string")}, + {('e'), QLatin1String("expandtopic")}, + {('r'), QLatin1String("remove~+")}, + {('e'), QLatin1String("extractpath")}, + {('n'), QLatin1String("need/")}, + {('p'), QLatin1String("pathsep?")}, + {('t'), QLatin1String("tfile")}, + {('o'), QLatin1String("ofile")}, + {('a'), QLatin1String("absolut-path?")}, + {('.'), QLatin1String(".fpath")}, + {('.'), QLatin1String(".path")}, + {('p'), QLatin1String("previous-path")}, + {('n'), QLatin1String("next-path")}, + {('p'), QLatin1String("path>string")}, + {('f'), QLatin1String("fpath=")}, + {('p'), QLatin1String("path=")}, + {('f'), QLatin1String("fpath+")}, + {('p'), QLatin1String("path+")}, + {('o'), QLatin1String("only-path")}, + {('c'), QLatin1String("clear-path")}, + {('a'), QLatin1String("also-path")}, + {('o'), QLatin1String("os-cold")}, + {('m'), QLatin1String("make-path")}, + {('f'), QLatin1String("fpath")}, + {('+'), QLatin1String("+place")}, + {('p'), QLatin1String("path-allot")}, + {('('), QLatin1String("(")}, + {('w'), QLatin1String("write-line")}, + {('b'), QLatin1String("bin")}, + {('r'), QLatin1String("r/o")}, + {('r'), QLatin1String("r/w")}, + {('w'), QLatin1String("w/o")}, + {('o'), QLatin1String("os-boot")}, + {('('), QLatin1String("(process-args)")}, + {('p'), QLatin1String("process-option")}, + {('a'), QLatin1String("args-evaluate")}, + {('a'), QLatin1String("args-required")}, + {('a'), QLatin1String("args-required1")}, + {('o'), QLatin1String("os-execute-parsing")}, + {('n'), QLatin1String("next-arg")}, + {('s'), QLatin1String("shift-args")}, + {('s'), QLatin1String("script?")}, + {('a'), QLatin1String("argc")}, + {('a'), QLatin1String("argv")}, + {('p'), QLatin1String("pathdirs")}, + {('p'), QLatin1String("pathstring")}, + {('#'), QLatin1String("#!")}, + {('a'), QLatin1String("arg")}, + {('c'), QLatin1String("cstring>sstring")}, + {('s'), QLatin1String("set-encoding-fixed-width")}, + {('c'), QLatin1String("c-size")}, + {('c'), QLatin1String("c!+?")}, + {('s'), QLatin1String("string-")}, + {('+'), QLatin1String("+string")}, + {('c'), QLatin1String("char-")}, + {('x'), QLatin1String("xhold")}, + {('x'), QLatin1String("x@+/string")}, + {('-'), QLatin1String("-trailing-garbage")}, + {('x'), QLatin1String("x-width")}, + {('x'), QLatin1String("x-size")}, + {('x'), QLatin1String("xc-size")}, + {('x'), QLatin1String("xc@+")}, + {('x'), QLatin1String("xc!+?")}, + {('x'), QLatin1String("xc@")}, + {('x'), QLatin1String("x\\string-")}, + {('+'), QLatin1String("+x/string")}, + {('x'), QLatin1String("xchar-")}, + {('x'), QLatin1String("xchar+")}, + {('x'), QLatin1String("xkey")}, + {('x'), QLatin1String("xemit")}, + {('l'), QLatin1String("license")}, + {('i'), QLatin1String("include-file")}, + {('e'), QLatin1String("execute-parsing-file")}, + {('e'), QLatin1String("execute-parsing-named-file")}, + {('r'), QLatin1String("read-loop")}, + {('l'), QLatin1String("line-end-hook")}, + {('q'), QLatin1String("query")}, + {('c'), QLatin1String("clear-tibstack")}, + {('e'), QLatin1String("evaluate")}, + {('e'), QLatin1String("execute-parsing")}, + {('e'), QLatin1String("execute-parsing-wrapper")}, + {('c'), QLatin1String("create-input")}, + {('r'), QLatin1String("restore-input")}, + {('s'), QLatin1String("save-input")}, + {('p'), QLatin1String("pop-file")}, + {('p'), QLatin1String("push-file")}, + {('e'), QLatin1String("expand-tib")}, + {('n'), QLatin1String("new-tib")}, + {('f'), QLatin1String("file-input")}, + {('r'), QLatin1String("read-line")}, + {('e'), QLatin1String("evaluate-input")}, + {('t'), QLatin1String("terminal-input")}, + {('i'), QLatin1String("input-start-line")}, + {('i'), QLatin1String("input-lexeme!")}, + {('t'), QLatin1String("tib+")}, + {('t'), QLatin1String("tib")}, + {('l'), QLatin1String("loadfilename")}, + {('#'), QLatin1String("#fill-bytes")}, + {('b'), QLatin1String("blk")}, + {('l'), QLatin1String("loadfile")}, + {('l'), QLatin1String("loadline")}, + {('o'), QLatin1String("old-input")}, + {('m'), QLatin1String("max#tib")}, + {('#'), QLatin1String("#tib")}, + {('i'), QLatin1String("input-lexeme")}, + {('>'), QLatin1String(">in")}, + {('('), QLatin1String("(restore-input)")}, + {('('), QLatin1String("(save-input)")}, + {('s'), QLatin1String("source-id")}, + {('r'), QLatin1String("refill")}, + {('s'), QLatin1String("source")}, + {('i'), QLatin1String("input-var")}, + {('i'), QLatin1String("input-method")}, + {('a'), QLatin1String("accept")}, + {('e'), QLatin1String("edit-line")}, + {('d'), QLatin1String("decode")}, + {('e'), QLatin1String("everyline")}, + {('e'), QLatin1String("everychar")}, + {('i'), QLatin1String("insert-char")}, + {('c'), QLatin1String("ctrlkeys")}, + {('('), QLatin1String("(ret)")}, + {('('), QLatin1String("(bs)")}, + {('('), QLatin1String("(ins)")}, + {('r'), QLatin1String("recursive")}, + {('r'), QLatin1String("rehash")}, + {('r'), QLatin1String("reveal")}, + {('c'), QLatin1String("check-shadow")}, + {('('), QLatin1String("(reveal)")}, + {('w'), QLatin1String("warnings")}, + {('l'), QLatin1String("last?")}, + {(';'), QLatin1String(";")}, + {(':'), QLatin1String(":noname")}, + {(':'), QLatin1String(":")}, + {('('), QLatin1String("(:noname)")}, + {('d'), QLatin1String("defstart")}, + {(';'), QLatin1String(";-hook")}, + {(':'), QLatin1String(":-hook")}, + {('i'), QLatin1String("interpret/compile?")}, + {('T'), QLatin1String("TO")}, + {('I'), QLatin1String("IS")}, + {('['), QLatin1String("[IS]")}, + {('<'), QLatin1String("")}, + {('d'), QLatin1String("defer!")}, + {('D'), QLatin1String("DOES>")}, + {('D'), QLatin1String("Defers")}, + {('d'), QLatin1String("defer@")}, + {('D'), QLatin1String("Defer")}, + {('d'), QLatin1String("defer-default")}, + {('i'), QLatin1String("interpret/compile:")}, + {('i'), QLatin1String("interpret/compile-struct")}, + {('i'), QLatin1String("interpret/compile-comp")}, + {('i'), QLatin1String("interpret/compile-int")}, + {('('), QLatin1String("(Field)")}, + {('2'), QLatin1String("2Constant")}, + {('A'), QLatin1String("AValue")}, + {('V'), QLatin1String("Value")}, + {('A'), QLatin1String("AConstant")}, + {('C'), QLatin1String("Constant")}, + {('('), QLatin1String("(Value)")}, + {('('), QLatin1String("(Constant)")}, + {('A'), QLatin1String("AUser")}, + {('U'), QLatin1String("User")}, + {('u'), QLatin1String("uallot")}, + {('2'), QLatin1String("2Variable")}, + {('A'), QLatin1String("AVariable")}, + {('V'), QLatin1String("Variable")}, + {('C'), QLatin1String("Create")}, + {('A'), QLatin1String("Alias")}, + {('c'), QLatin1String("compile-only")}, + {('r'), QLatin1String("restrict")}, + {('i'), QLatin1String("immediate")}, + {('l'), QLatin1String("lastflags")}, + {('c'), QLatin1String("ctoggle")}, + {('c'), QLatin1String("creset")}, + {('c'), QLatin1String("cset")}, + {(','), QLatin1String(",\"")}, + {('m'), QLatin1String("mem,")}, + {('S'), QLatin1String("S,")}, + {(']'), QLatin1String("]")}, + {('['), QLatin1String("[")}, + {('c'), QLatin1String("compiler1")}, + {('r'), QLatin1String("recurse")}, + {('P'), QLatin1String("POSTPONE")}, + {('p'), QLatin1String("postpone,")}, + {('['), QLatin1String("[COMP']")}, + {('C'), QLatin1String("COMP'")}, + {('['), QLatin1String("[']")}, + {('['), QLatin1String("[(')]")}, + {('n'), QLatin1String("name>comp")}, + {('('), QLatin1String("(compile)")}, + {('d'), QLatin1String("dodoes,")}, + {('('), QLatin1String("(does>2)")}, + {('('), QLatin1String("(does>)")}, + {('!'), QLatin1String("!does")}, + {('c'), QLatin1String("compile-to-prims,")}, + {('p'), QLatin1String("peephole-compile,")}, + {('b'), QLatin1String("basic-block-end")}, + {('c'), QLatin1String("compile,")}, + {('c'), QLatin1String("cfa,")}, + {('['), QLatin1String("[char]")}, + {('c'), QLatin1String("char")}, + {('c'), QLatin1String("char@")}, + {('A'), QLatin1String("ALiteral")}, + {('2'), QLatin1String("2Literal")}, + {('L'), QLatin1String("Literal")}, + {('l'), QLatin1String("latest")}, + {('l'), QLatin1String("lastxt")}, + {('l'), QLatin1String("latestxt")}, + {('n'), QLatin1String("noname")}, + {('n'), QLatin1String("noname-header")}, + {('n'), QLatin1String("nextname")}, + {('n'), QLatin1String("nextname-header")}, + {('n'), QLatin1String("nextname-string")}, + {('i'), QLatin1String("input-stream")}, + {('i'), QLatin1String("input-stream-header")}, + {('h'), QLatin1String("header,")}, + {('l'), QLatin1String("longstring,")}, + {('s'), QLatin1String("string,")}, + {('h'), QLatin1String("header")}, + {('('), QLatin1String("(header)")}, + {('c'), QLatin1String("const")}, + {('A'), QLatin1String("A,")}, + {('c'), QLatin1String("cfalign")}, + {('m'), QLatin1String("maxalign")}, + {('f'), QLatin1String("falign")}, + {('a'), QLatin1String("align")}, + {('2'), QLatin1String("2,")}, + {(','), QLatin1String(",")}, + {('c'), QLatin1String("c,")}, + {('a'), QLatin1String("allot")}, + {('b'), QLatin1String("bye")}, + {('b'), QLatin1String("boot")}, + {('c'), QLatin1String("cold")}, + {('\''), QLatin1String("'cold")}, + {('p'), QLatin1String("process-args")}, + {('b'), QLatin1String("bootmessage")}, + {('('), QLatin1String("(bootmessage)")}, + {('q'), QLatin1String("quit")}, + {('('), QLatin1String("(DoError)")}, + {('.'), QLatin1String(".error-frame")}, + {('.'), QLatin1String(".error-line")}, + {('p'), QLatin1String("part-type")}, + {('m'), QLatin1String("mark-end")}, + {('m'), QLatin1String("mark-start")}, + {('u'), QLatin1String("umin")}, + {('.'), QLatin1String(".error-string")}, + {('d'), QLatin1String("dobacktrace")}, + {('D'), QLatin1String("DOERROR")}, + {('-'), QLatin1String("-trailing")}, + {('h'), QLatin1String("hex.")}, + {('d'), QLatin1String("dec.r")}, + {('d'), QLatin1String("dec.")}, + {('i'), QLatin1String("input-error-data")}, + {('>'), QLatin1String(">error")}, + {('e'), QLatin1String("error>")}, + {('e'), QLatin1String("error-stack")}, + {('/'), QLatin1String("/error")}, + {('m'), QLatin1String("max-errors")}, + {('('), QLatin1String("(quit)")}, + {('p'), QLatin1String("prompt")}, + {('.'), QLatin1String(".status")}, + {('\''), QLatin1String("'quit")}, + {('e'), QLatin1String("extend-mem")}, + {('f'), QLatin1String("free-mem-var")}, + {('s'), QLatin1String("save-mem")}, + {('i'), QLatin1String("interpreter1")}, + {('i'), QLatin1String("interpret")}, + {('i'), QLatin1String("interpret1")}, + {('b'), QLatin1String("before-word")}, + {('n'), QLatin1String("no.extensions")}, + {('i'), QLatin1String("interpreter-notfound1")}, + {('c'), QLatin1String("compiler-notfound1")}, + {('n'), QLatin1String("name")}, + {('p'), QLatin1String("parse-word")}, + {('p'), QLatin1String("parse-name")}, + {('p'), QLatin1String("parser")}, + {('p'), QLatin1String("parser1")}, + {('\''), QLatin1String("'")}, + {('('), QLatin1String("(')")}, + {('f'), QLatin1String("find")}, + {('s'), QLatin1String("sfind")}, + {('/'), QLatin1String("/does-handler")}, + {('d'), QLatin1String("does-handler!")}, + {('d'), QLatin1String("does-code!")}, + {('c'), QLatin1String("code-address!")}, + {('f'), QLatin1String("flashc!")}, + {('f'), QLatin1String("flash!")}, + {('>'), QLatin1String(">does-code")}, + {('>'), QLatin1String(">code-address")}, + {('b'), QLatin1String("body>")}, + {('>'), QLatin1String(">body")}, + {('>'), QLatin1String(">head-noprim")}, + {('h'), QLatin1String("head?")}, + {('?'), QLatin1String("???")}, + {('('), QLatin1String("(name>intn)")}, + {('('), QLatin1String("(name>comp)")}, + {('n'), QLatin1String("name?int")}, + {('n'), QLatin1String("name>int")}, + {('('), QLatin1String("(name>x)")}, + {('('), QLatin1String("((name>))")}, + {('n'), QLatin1String("name>string")}, + {('('), QLatin1String("(x>int)")}, + {('('), QLatin1String("(cfa>int)")}, + {('c'), QLatin1String("compile-only-error")}, + {('t'), QLatin1String("ticking-compile-only-error")}, + {('f'), QLatin1String("flag-sign")}, + {('l'), QLatin1String("lcount-mask")}, + {('r'), QLatin1String("restrict-mask")}, + {('i'), QLatin1String("immediate-mask")}, + {('a'), QLatin1String("alias-mask")}, + {('f'), QLatin1String("find-name")}, + {('s'), QLatin1String("search-wordlist")}, + {('('), QLatin1String("(search-wordlist)")}, + {('c'), QLatin1String("context")}, + {('v'), QLatin1String("voclink")}, + {('c'), QLatin1String("current")}, + {('l'), QLatin1String("lookup")}, + {('f'), QLatin1String("forth-wordlist")}, + {('f'), QLatin1String("f83search")}, + {('i'), QLatin1String("initvoc")}, + {('f'), QLatin1String("f83find")}, + {('w'), QLatin1String("wordlist-struct")}, + {('w'), QLatin1String("wordlist-extend")}, + {('w'), QLatin1String("wordlist-link")}, + {('w'), QLatin1String("wordlist-id")}, + {('w'), QLatin1String("wordlist-map")}, + {('w'), QLatin1String("wordlist-map-struct")}, + {('h'), QLatin1String("hash-method")}, + {('r'), QLatin1String("rehash-method")}, + {('r'), QLatin1String("reveal-method")}, + {('f'), QLatin1String("find-method")}, + {('\\'), QLatin1String("\\G")}, + {('\\'), QLatin1String("\\")}, + {('('), QLatin1String("(")}, + {('n'), QLatin1String("number")}, + {('n'), QLatin1String("number?")}, + {('s'), QLatin1String("snumber?")}, + {('s'), QLatin1String("s>number")}, + {('s'), QLatin1String("s>number?")}, + {('s'), QLatin1String("s>unumber?")}, + {('s'), QLatin1String("s'>unumber?")}, + {('?'), QLatin1String("?dnegate")}, + {('s'), QLatin1String("sign?")}, + {('g'), QLatin1String("getbase")}, + {('b'), QLatin1String("bases")}, + {('n'), QLatin1String("name-too-long?")}, + {('n'), QLatin1String("name-too-short?")}, + {('('), QLatin1String("(name)")}, + {('p'), QLatin1String("parse")}, + {('w'), QLatin1String("word")}, + {('s'), QLatin1String("sword")}, + {('('), QLatin1String("(word)")}, + {('v'), QLatin1String("version-string")}, + {('.'), QLatin1String(".error")}, + {('>'), QLatin1String(">stderr")}, + {('E'), QLatin1String("ErrLink")}, + {('u'), QLatin1String("u.")}, + {('.'), QLatin1String(".")}, + {('u'), QLatin1String("ud.")}, + {('d'), QLatin1String("d.")}, + {('u'), QLatin1String("u.r")}, + {('.'), QLatin1String(".r")}, + {('u'), QLatin1String("ud.r")}, + {('d'), QLatin1String("d.r")}, + {('#'), QLatin1String("#s")}, + {('#'), QLatin1String("#")}, + {('s'), QLatin1String("sign")}, + {('#'), QLatin1String("#>>")}, + {('<'), QLatin1String("<<#")}, + {('#'), QLatin1String("#>")}, + {('<'), QLatin1String("<#")}, + {('h'), QLatin1String("hold")}, + {('p'), QLatin1String("pad")}, + {('b'), QLatin1String("backspaces")}, + {('s'), QLatin1String("spaces")}, + {('s'), QLatin1String("space")}, + {('c'), QLatin1String("cr")}, + {('b'), QLatin1String("bell")}, + {('#'), QLatin1String("#lf")}, + {('#'), QLatin1String("#ff")}, + {('#'), QLatin1String("#cr")}, + {('#'), QLatin1String("#del")}, + {('#'), QLatin1String("#tab")}, + {('#'), QLatin1String("#bs")}, + {('#'), QLatin1String("#bell")}, + {('#'), QLatin1String("#eof")}, + {('('), QLatin1String("(S\")")}, + {('('), QLatin1String("(.\")")}, + {('k'), QLatin1String("key?")}, + {('k'), QLatin1String("key")}, + {('e'), QLatin1String("emit")}, + {('t'), QLatin1String("type")}, + {('('), QLatin1String("(key?)")}, + {('('), QLatin1String("(key)")}, + {('('), QLatin1String("(emit)")}, + {('('), QLatin1String("(type)")}, + {('i'), QLatin1String("infile-id")}, + {('o'), QLatin1String("outfile-id")}, + {('h'), QLatin1String("hex")}, + {('d'), QLatin1String("decimal")}, + {('"'), QLatin1String("\"lit")}, + {('c'), QLatin1String("clearstacks")}, + {('c'), QLatin1String("clearstack")}, + {('d'), QLatin1String("depth")}, + {('?'), QLatin1String("?stack")}, + {('a'), QLatin1String("abort")}, + {('('), QLatin1String("(abort\")")}, + {('c'), QLatin1String("c(abort\")")}, + {('t'), QLatin1String("throw")}, + {('c'), QLatin1String("catch")}, + {('l'), QLatin1String("lp@")}, + {('u'), QLatin1String("ud/mod")}, + {('s'), QLatin1String("s>d")}, + {('>'), QLatin1String(">number")}, + {('a'), QLatin1String("accumulate")}, + {('d'), QLatin1String("digit?")}, + {('s'), QLatin1String("skip")}, + {('s'), QLatin1String("scan")}, + {('b'), QLatin1String("bounds")}, + {('p'), QLatin1String("place")}, + {('r'), QLatin1String("roll")}, + {('d'), QLatin1String("dabs")}, + {('o'), QLatin1String("off")}, + {('o'), QLatin1String("on")}, + {('h'), QLatin1String("here")}, + {('d'), QLatin1String("dp")}, + {('i'), QLatin1String("in-dictionary?")}, + {('u'), QLatin1String("unused")}, + {('u'), QLatin1String("usable-dictionary-end")}, + {('d'), QLatin1String("dictionary-end")}, + {('A'), QLatin1String("A!")}, + {('c'), QLatin1String("chars")}, + {('c'), QLatin1String("cfaligned")}, + {('m'), QLatin1String("maxaligned")}, + {('r'), QLatin1String("r@")}, + {('N'), QLatin1String("NIL")}, + {('s'), QLatin1String("str<")}, + {('s'), QLatin1String("string-prefix?")}, + {('s'), QLatin1String("str=")}, + {('l'), QLatin1String("locals-size")}, + {('m'), QLatin1String("max-name-length")}, + {('L'), QLatin1String("Last")}, + {('L'), QLatin1String("LastCFA")}, + {('d'), QLatin1String("dpp")}, + {('n'), QLatin1String("normal-dp")}, + {('s'), QLatin1String("state")}, + {('d'), QLatin1String("dpl")}, + {('b'), QLatin1String("base")}, + {('i'), QLatin1String("includefilename")}, + {('c'), QLatin1String("current-input")}, + {('"'), QLatin1String("\"error")}, + {('e'), QLatin1String("errorhandler")}, + {('b'), QLatin1String("backtrace-rp0")}, + {('h'), QLatin1String("handler")}, + {('l'), QLatin1String("lp0")}, + {('f'), QLatin1String("fp0")}, + {('r'), QLatin1String("rp0")}, + {('s'), QLatin1String("sp0")}, + {('s'), QLatin1String("save-task")}, + {('p'), QLatin1String("prev-task")}, + {('n'), QLatin1String("next-task")}, + {('u'), QLatin1String("udp")}, + {('m'), QLatin1String("main-task")}, + {('d'), QLatin1String("def#tib")}, + {('p'), QLatin1String("pad-minsize")}, + {('h'), QLatin1String("holdend")}, + {('h'), QLatin1String("holdptr")}, + {('h'), QLatin1String("holdbuf-end")}, + {('h'), QLatin1String("holdbuf")}, + {('w'), QLatin1String("word-pno-size")}, + {('c'), QLatin1String("chars/block")}, + {('l'), QLatin1String("l/s")}, + {('c'), QLatin1String("c/l")}, + {('/'), QLatin1String("/line")}, + {('b'), QLatin1String("bl")}, + {('f'), QLatin1String("float")}, + {('c'), QLatin1String("cell")}, + {('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + {('f'), QLatin1String("forthstart")}, + {('i'), QLatin1String("image-header")}, + {('t'), QLatin1String("tag-offsets")}, + {('c'), QLatin1String("call2")}, + {('s'), QLatin1String("set-next-code")}, + {('d'), QLatin1String("decompile-prim")}, + {('f'), QLatin1String("forget-dyncode")}, + {('f'), QLatin1String("finish-code")}, + {('c'), QLatin1String("compile-prim1")}, + {('l'), QLatin1String("lib-error")}, + {('l'), QLatin1String("l!")}, + {('s'), QLatin1String("sl@")}, + {('u'), QLatin1String("ul@")}, + {('w'), QLatin1String("w!")}, + {('s'), QLatin1String("sw@")}, + {('u'), QLatin1String("uw@")}, + {('w'), QLatin1String("wcall")}, + {('l'), QLatin1String("lib-sym")}, + {('o'), QLatin1String("open-lib")}, + {('f'), QLatin1String("fpick")}, + {('f'), QLatin1String("f>l")}, + {('>'), QLatin1String(">l")}, + {('l'), QLatin1String("lp!")}, + {('l'), QLatin1String("lp+2")}, + {('l'), QLatin1String("lp+")}, + {('l'), QLatin1String("lp-")}, + {('l'), QLatin1String("lp+!#")}, + {('l'), QLatin1String("laddr#")}, + {('f'), QLatin1String("f@local1")}, + {('f'), QLatin1String("f@local0")}, + {('f'), QLatin1String("f@local#")}, + {('@'), QLatin1String("@local3")}, + {('@'), QLatin1String("@local2")}, + {('@'), QLatin1String("@local1")}, + {('@'), QLatin1String("@local0")}, + {('@'), QLatin1String("@local#")}, + {('f'), QLatin1String("faxpy")}, + {('v'), QLatin1String("v*")}, + {('d'), QLatin1String("dfaligned")}, + {('s'), QLatin1String("sfaligned")}, + {('d'), QLatin1String("dfloats")}, + {('s'), QLatin1String("sfloats")}, + {('f'), QLatin1String("fatanh")}, + {('f'), QLatin1String("facosh")}, + {('f'), QLatin1String("fasinh")}, + {('f'), QLatin1String("ftanh")}, + {('f'), QLatin1String("fcosh")}, + {('f'), QLatin1String("fsinh")}, + {('f'), QLatin1String("ftan")}, + {('f'), QLatin1String("fsqrt")}, + {('f'), QLatin1String("fsincos")}, + {('f'), QLatin1String("fsin")}, + {('f'), QLatin1String("falog")}, + {('f'), QLatin1String("flog")}, + {('f'), QLatin1String("flnp1")}, + {('f'), QLatin1String("fln")}, + {('f'), QLatin1String("fexpm1")}, + {('f'), QLatin1String("fexp")}, + {('f'), QLatin1String("fcos")}, + {('f'), QLatin1String("fatan2")}, + {('f'), QLatin1String("fatan")}, + {('f'), QLatin1String("fasin")}, + {('f'), QLatin1String("facos")}, + {('f'), QLatin1String("fabs")}, + {('>'), QLatin1String(">float")}, + {('r'), QLatin1String("represent")}, + {('f'), QLatin1String("fmin")}, + {('f'), QLatin1String("fmax")}, + {('f'), QLatin1String("fround")}, + {('f'), QLatin1String("floor")}, + {('f'), QLatin1String("floats")}, + {('f'), QLatin1String("float+")}, + {('f'), QLatin1String("ftuck")}, + {('f'), QLatin1String("fnip")}, + {('f'), QLatin1String("frot")}, + {('f'), QLatin1String("fover")}, + {('f'), QLatin1String("fswap")}, + {('f'), QLatin1String("fdup")}, + {('f'), QLatin1String("fdrop")}, + {('f'), QLatin1String("fnegate")}, + {('f'), QLatin1String("f**2")}, + {('f'), QLatin1String("fm*/")}, + {('f'), QLatin1String("fm/")}, + {('f'), QLatin1String("fm*")}, + {('f'), QLatin1String("f**")}, + {('f'), QLatin1String("f/")}, + {('f'), QLatin1String("f*")}, + {('f'), QLatin1String("f-")}, + {('f'), QLatin1String("f+")}, + {('s'), QLatin1String("sf!")}, + {('s'), QLatin1String("sf@")}, + {('d'), QLatin1String("df!")}, + {('d'), QLatin1String("df@")}, + {('f'), QLatin1String("f@")}, + {('f'), QLatin1String("f!")}, + {('f'), QLatin1String("f>s")}, + {('f'), QLatin1String("f>d")}, + {('d'), QLatin1String("d>f")}, + {('s'), QLatin1String("s>f")}, + {('f'), QLatin1String("f0>=")}, + {('f'), QLatin1String("f0<=")}, + {('f'), QLatin1String("f0>")}, + {('f'), QLatin1String("f0<")}, + {('f'), QLatin1String("f0<>")}, + {('f'), QLatin1String("f0=")}, + {('f'), QLatin1String("f>=")}, + {('f'), QLatin1String("f<=")}, + {('f'), QLatin1String("f>")}, + {('f'), QLatin1String("f<")}, + {('f'), QLatin1String("f<>")}, + {('f'), QLatin1String("f=")}, + {('c'), QLatin1String("cputime")}, + {('u'), QLatin1String("utime")}, + {('n'), QLatin1String("newline")}, + {('='), QLatin1String("=mkdir")}, + {('g'), QLatin1String("get-dir")}, + {('s'), QLatin1String("set-dir")}, + {('f'), QLatin1String("filename-match")}, + {('c'), QLatin1String("close-dir")}, + {('r'), QLatin1String("read-dir")}, + {('o'), QLatin1String("open-dir")}, + {('f'), QLatin1String("file-eof?")}, + {('f'), QLatin1String("file-status")}, + {('f'), QLatin1String("flush-file")}, + {('e'), QLatin1String("emit-file")}, + {('w'), QLatin1String("write-file")}, + {('('), QLatin1String("(read-line)")}, + {('r'), QLatin1String("read-file")}, + {('r'), QLatin1String("resize-file")}, + {('f'), QLatin1String("file-size")}, + {('r'), QLatin1String("reposition-file")}, + {('f'), QLatin1String("file-position")}, + {('r'), QLatin1String("rename-file")}, + {('d'), QLatin1String("delete-file")}, + {('c'), QLatin1String("create-file")}, + {('o'), QLatin1String("open-file")}, + {('c'), QLatin1String("close-file")}, + {('c'), QLatin1String("call-c")}, + {('s'), QLatin1String("strsignal")}, + {('s'), QLatin1String("strerror")}, + {('r'), QLatin1String("resize")}, + {('f'), QLatin1String("free")}, + {('a'), QLatin1String("allocate")}, + {('m'), QLatin1String("ms")}, + {('t'), QLatin1String("time&date")}, + {('c'), QLatin1String("close-pipe")}, + {('o'), QLatin1String("open-pipe")}, + {('g'), QLatin1String("getenv")}, + {('('), QLatin1String("(system)")}, + {('('), QLatin1String("(bye)")}, + {('f'), QLatin1String("flush-icache")}, + {('w'), QLatin1String("wcwidth")}, + {('f'), QLatin1String("form")}, + {('s'), QLatin1String("stderr")}, + {('s'), QLatin1String("stdout")}, + {('s'), QLatin1String("stdin")}, + {('k'), QLatin1String("key?-file")}, + {('k'), QLatin1String("key-file")}, + {('t'), QLatin1String("threading-method")}, + {('f'), QLatin1String("faligned")}, + {('a'), QLatin1String("aligned")}, + {('('), QLatin1String("(parse-white)")}, + {('('), QLatin1String("(hashkey1)")}, + {('('), QLatin1String("(tablelfind)")}, + {('('), QLatin1String("(hashlfind)")}, + {('('), QLatin1String("(listlfind)")}, + {('c'), QLatin1String("count")}, + {('('), QLatin1String("(chars)")}, + {('c'), QLatin1String("char+")}, + {('c'), QLatin1String("cells")}, + {('c'), QLatin1String("cell+")}, + {('2'), QLatin1String("2@")}, + {('2'), QLatin1String("2!")}, + {('c'), QLatin1String("c!")}, + {('c'), QLatin1String("c@")}, + {('+'), QLatin1String("+!")}, + {('!'), QLatin1String("!")}, + {('l'), QLatin1String("lit@")}, + {('@'), QLatin1String("@")}, + {('2'), QLatin1String("2tuck")}, + {('2'), QLatin1String("2nip")}, + {('2'), QLatin1String("2rot")}, + {('2'), QLatin1String("2swap")}, + {('2'), QLatin1String("2over")}, + {('2'), QLatin1String("2dup")}, + {('2'), QLatin1String("2drop")}, + {('p'), QLatin1String("pick")}, + {('?'), QLatin1String("?dup")}, + {('t'), QLatin1String("tuck")}, + {('n'), QLatin1String("nip")}, + {('-'), QLatin1String("-rot")}, + {('r'), QLatin1String("rot")}, + {('d'), QLatin1String("dup")}, + {('s'), QLatin1String("swap")}, + {('d'), QLatin1String("drop")}, + {('o'), QLatin1String("over")}, + {('2'), QLatin1String("2rdrop")}, + {('2'), QLatin1String("2r@")}, + {('2'), QLatin1String("2r>")}, + {('2'), QLatin1String("2>r")}, + {('r'), QLatin1String("rdrop")}, + {('r'), QLatin1String("r>")}, + {('>'), QLatin1String(">r")}, + {('f'), QLatin1String("fp!")}, + {('f'), QLatin1String("fp@")}, + {('r'), QLatin1String("rp!")}, + {('r'), QLatin1String("rp@")}, + {('s'), QLatin1String("sp!")}, + {('s'), QLatin1String("sp@")}, + {('u'), QLatin1String("up!")}, + {('u'), QLatin1String("useraddr")}, + {('w'), QLatin1String("within")}, + {('d'), QLatin1String("du>=")}, + {('d'), QLatin1String("du<=")}, + {('d'), QLatin1String("du>")}, + {('d'), QLatin1String("du<")}, + {('d'), QLatin1String("du<>")}, + {('d'), QLatin1String("du=")}, + {('d'), QLatin1String("d0>=")}, + {('d'), QLatin1String("d0<=")}, + {('d'), QLatin1String("d0>")}, + {('d'), QLatin1String("d0<")}, + {('d'), QLatin1String("d0<>")}, + {('d'), QLatin1String("d0=")}, + {('d'), QLatin1String("d>=")}, + {('d'), QLatin1String("d<=")}, + {('d'), QLatin1String("d>")}, + {('d'), QLatin1String("d<")}, + {('d'), QLatin1String("d<>")}, + {('d'), QLatin1String("d=")}, + {('u'), QLatin1String("u>=")}, + {('u'), QLatin1String("u<=")}, + {('u'), QLatin1String("u>")}, + {('u'), QLatin1String("u<")}, + {('u'), QLatin1String("u<>")}, + {('u'), QLatin1String("u=")}, + {('>'), QLatin1String(">=")}, + {('<'), QLatin1String("<=")}, + {('>'), QLatin1String(">")}, + {('<'), QLatin1String("<")}, + {('<'), QLatin1String("<>")}, + {('='), QLatin1String("=")}, + {('0'), QLatin1String("0>=")}, + {('0'), QLatin1String("0<=")}, + {('0'), QLatin1String("0>")}, + {('0'), QLatin1String("0<")}, + {('0'), QLatin1String("0<>")}, + {('0'), QLatin1String("0=")}, + {('l'), QLatin1String("lshift")}, + {('r'), QLatin1String("rshift")}, + {('i'), QLatin1String("invert")}, + {('x'), QLatin1String("xor")}, + {('o'), QLatin1String("or")}, + {('a'), QLatin1String("and")}, + {('d'), QLatin1String("d2/")}, + {('d'), QLatin1String("d2*")}, + {('d'), QLatin1String("dnegate")}, + {('d'), QLatin1String("d-")}, + {('d'), QLatin1String("d+")}, + {('m'), QLatin1String("m+")}, + {('u'), QLatin1String("um/mod")}, + {('u'), QLatin1String("um*")}, + {('m'), QLatin1String("m*")}, + {('s'), QLatin1String("sm/rem")}, + {('f'), QLatin1String("fm/mod")}, + {('2'), QLatin1String("2/")}, + {('2'), QLatin1String("2*")}, + {('*'), QLatin1String("*/")}, + {('*'), QLatin1String("*/mod")}, + {('/'), QLatin1String("/mod")}, + {('m'), QLatin1String("mod")}, + {('/'), QLatin1String("/")}, + {('*'), QLatin1String("*")}, + {('a'), QLatin1String("abs")}, + {('m'), QLatin1String("min")}, + {('m'), QLatin1String("max")}, + {('1'), QLatin1String("1-")}, + {('1'), QLatin1String("1+")}, + {('n'), QLatin1String("negate")}, + {('-'), QLatin1String("-")}, + {('u'), QLatin1String("under+")}, + {('l'), QLatin1String("lit+")}, + {('+'), QLatin1String("+")}, + {('l'), QLatin1String("lit")}, + {('/'), QLatin1String("/string")}, + {('c'), QLatin1String("capscompare")}, + {('t'), QLatin1String("toupper")}, + {('c'), QLatin1String("compare")}, + {('f'), QLatin1String("fill")}, + {('c'), QLatin1String("cmove>")}, + {('c'), QLatin1String("cmove")}, + {('m'), QLatin1String("move")}, + {('k'), QLatin1String("k")}, + {('j'), QLatin1String("j")}, + {('i'), QLatin1String("i'")}, + {('i'), QLatin1String("i")}, + {('('), QLatin1String("(u-do)")}, + {('('), QLatin1String("(-do)")}, + {('('), QLatin1String("(u+do)")}, + {('('), QLatin1String("(+do)")}, + {('('), QLatin1String("(?do)")}, + {('('), QLatin1String("(do)")}, + {('('), QLatin1String("(for)")}, + {('('), QLatin1String("(s+loop)-lp+!#")}, + {('('), QLatin1String("(s+loop)")}, + {('('), QLatin1String("(-loop)-lp+!#")}, + {('('), QLatin1String("(-loop)")}, + {('('), QLatin1String("(+loop)-lp+!#")}, + {('('), QLatin1String("(+loop)")}, + {('('), QLatin1String("(loop)-lp+!#")}, + {('('), QLatin1String("(loop)")}, + {('('), QLatin1String("(next)-lp+!#")}, + {('('), QLatin1String("(next)")}, + {('?'), QLatin1String("?dup-0=-?branch")}, + {('?'), QLatin1String("?dup-?branch")}, + {('?'), QLatin1String("?branch-lp+!#")}, + {('?'), QLatin1String("?branch")}, + {('b'), QLatin1String("branch")}, + {('b'), QLatin1String("branch-lp+!#")}, + {('d'), QLatin1String("does-exec")}, + {('l'), QLatin1String("lit-perform")}, + {('u'), QLatin1String("unloop")}, + {(';'), QLatin1String(";s")}, + {('p'), QLatin1String("perform")}, + {('e'), QLatin1String("execute")}, + {('c'), QLatin1String("call")}, + {('n'), QLatin1String("noop")}, + }; + + forth_types = {}; + + forth_literals = {}; + + forth_builtin = {}; + + forth_other = {}; +} +void loadForthData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!forthDataInitialized) { + initForthData(); + forthDataInitialized = true; + } + types = forth_types; + keywords = forth_keywords; + builtin = forth_builtin; + literals = forth_literals; + other = forth_other; +} + +/**********************************************************/ +/* GDScript Data *********************************************/ +/**********************************************************/ + +static bool gdscriptDataInitialized = false; +static QMultiHash gdscript_keywords; +static QMultiHash gdscript_types; +static QMultiHash gdscript_literals; +static QMultiHash gdscript_builtin; +static QMultiHash gdscript_other; +void initGDScriptData() { + gdscript_keywords = { + {('i'), QLatin1String("if")}, + {('e'), QLatin1String("elif")}, + {('e'), QLatin1String("else")}, + {('f'), QLatin1String("for")}, + {('w'), QLatin1String("while")}, + {('m'), QLatin1String("match")}, + {('w'), QLatin1String("when")}, + {('b'), QLatin1String("break")}, + {('c'), QLatin1String("continue")}, + {('p'), QLatin1String("pass")}, + {('r'), QLatin1String("return")}, + {('c'), QLatin1String("class")}, + {('c'), QLatin1String("class_name")}, + {('e'), QLatin1String("extends")}, + {('i'), QLatin1String("is")}, + {('i'), QLatin1String("in")}, + {('a'), QLatin1String("as")}, + {('g'), QLatin1String("get")}, + {('s'), QLatin1String("set")}, + {('s'), QLatin1String("self")}, + {('s'), QLatin1String("super")}, + {('s'), QLatin1String("signal")}, + {('f'), QLatin1String("func")}, + {('s'), QLatin1String("static")}, + {('c'), QLatin1String("const")}, + {('e'), QLatin1String("enum")}, + {('v'), QLatin1String("var")}, + {('b'), QLatin1String("breakpoint")}, + {('a'), QLatin1String("await")}, + {('y'), QLatin1String("yield")}, + {('P'), QLatin1String("PI")}, + {('T'), QLatin1String("TAU")}, + {('I'), QLatin1String("INF")}, + {('N'), QLatin1String("NAN")}, + }; + + gdscript_types = { + {('b'), QLatin1String("bool")}, + {('f'), QLatin1String("float")}, + {('i'), QLatin1String("int")}, + {('v'), QLatin1String("void")}, + /* Variant Types */ + {('V'), QLatin1String("Variant")}, + {('A'), QLatin1String("AABB")}, + {('A'), QLatin1String("Array")}, + {('B'), QLatin1String("Basis")}, + {('C'), QLatin1String("Callable")}, + {('C'), QLatin1String("Color")}, + {('D'), QLatin1String("Dictionary")}, + {('N'), QLatin1String("NodePath")}, + {('O'), QLatin1String("Object")}, + {('P'), QLatin1String("PackedByteArray")}, + {('P'), QLatin1String("PackedColorArray")}, + {('P'), QLatin1String("PackedFloat32Array")}, + {('P'), QLatin1String("PackedFloat64Array")}, + {('P'), QLatin1String("PackedInt32Array")}, + {('P'), QLatin1String("PackedInt64Array")}, + {('P'), QLatin1String("PackedStringArray")}, + {('P'), QLatin1String("PackedVector2Array")}, + {('P'), QLatin1String("PackedVector3Array")}, + {('P'), QLatin1String("PackedVector4Array")}, + {('P'), QLatin1String("Plane")}, + {('P'), QLatin1String("Projection")}, + {('Q'), QLatin1String("Quaternion")}, + {('R'), QLatin1String("Rect2")}, + {('R'), QLatin1String("Rect2i")}, + {('R'), QLatin1String("RID")}, + {('S'), QLatin1String("Signal")}, + {('S'), QLatin1String("String")}, + {('S'), QLatin1String("StringName")}, + {('T'), QLatin1String("Transform2D")}, + {('T'), QLatin1String("Transform3D")}, + {('V'), QLatin1String("Vector2")}, + {('V'), QLatin1String("Vector2i")}, + {('V'), QLatin1String("Vector3")}, + {('V'), QLatin1String("Vector3i")}, + {('V'), QLatin1String("Vector4")}, + {('V'), QLatin1String("Vector4i")}, + /* Nodes */ + {('N'), QLatin1String("Node")}, + {('A'), QLatin1String("AcceptDialog")}, + {('A'), QLatin1String("AnimatableBody2D")}, + {('A'), QLatin1String("AnimatableBody3D")}, + {('A'), QLatin1String("AnimatedSprite2D")}, + {('A'), QLatin1String("AnimatedSprite3D")}, + {('A'), QLatin1String("AnimationMixer")}, + {('A'), QLatin1String("AnimationPlayer")}, + {('A'), QLatin1String("AnimationTree")}, + {('A'), QLatin1String("Area2D")}, + {('A'), QLatin1String("Area3D")}, + {('A'), QLatin1String("AspectRatioContainer")}, + {('A'), QLatin1String("AudioListener2D")}, + {('A'), QLatin1String("AudioListener3D")}, + {('A'), QLatin1String("AudioStreamPlayer")}, + {('A'), QLatin1String("AudioStreamPlayer2D")}, + {('A'), QLatin1String("AudioStreamPlayer3D")}, + {('B'), QLatin1String("BackBufferCopy")}, + {('B'), QLatin1String("BaseButton")}, + {('B'), QLatin1String("Bone2D")}, + {('B'), QLatin1String("BoneAttachment3D")}, + {('B'), QLatin1String("BoxContainer")}, + {('B'), QLatin1String("Button")}, + {('C'), QLatin1String("Camera2D")}, + {('C'), QLatin1String("Camera3D")}, + {('C'), QLatin1String("CanvasGroup")}, + {('C'), QLatin1String("CanvasItem")}, + {('C'), QLatin1String("CanvasLayer")}, + {('C'), QLatin1String("CanvasModulate")}, + {('C'), QLatin1String("CenterContainer")}, + {('C'), QLatin1String("CharacterBody2D")}, + {('C'), QLatin1String("CharacterBody3D")}, + {('C'), QLatin1String("CheckBox")}, + {('C'), QLatin1String("CheckButton")}, + {('C'), QLatin1String("CodeEdit")}, + {('C'), QLatin1String("CollisionObject2D")}, + {('C'), QLatin1String("CollisionObject3D")}, + {('C'), QLatin1String("CollisionPolygon2D")}, + {('C'), QLatin1String("CollisionPolygon3D")}, + {('C'), QLatin1String("CollisionShape2D")}, + {('C'), QLatin1String("CollisionShape3D")}, + {('C'), QLatin1String("ColorPicker")}, + {('C'), QLatin1String("ColorPickerButton")}, + {('C'), QLatin1String("ColorRect")}, + {('C'), QLatin1String("ConeTwistJoint3D")}, + {('C'), QLatin1String("ConfirmationDialog")}, + {('C'), QLatin1String("Container")}, + {('C'), QLatin1String("Control")}, + {('C'), QLatin1String("CPUParticles2D")}, + {('C'), QLatin1String("CPUParticles3D")}, + {('C'), QLatin1String("CSGBox3D")}, + {('C'), QLatin1String("CSGCombiner3D")}, + {('C'), QLatin1String("CSGCylinder3D")}, + {('C'), QLatin1String("CSGMesh3D")}, + {('C'), QLatin1String("CSGPolygon3D")}, + {('C'), QLatin1String("CSGPrimitive3D")}, + {('C'), QLatin1String("CSGShape3D")}, + {('C'), QLatin1String("CSGSphere3D")}, + {('C'), QLatin1String("CSGTorus3D")}, + {('D'), QLatin1String("DampedSpringJoint2D")}, + {('D'), QLatin1String("Decal")}, + {('D'), QLatin1String("DirectionalLight2D")}, + {('D'), QLatin1String("DirectionalLight3D")}, + {('E'), QLatin1String("EditorCommandPalette")}, + {('E'), QLatin1String("EditorFileDialog")}, + {('E'), QLatin1String("EditorFileSystem")}, + {('E'), QLatin1String("EditorInspector")}, + {('E'), QLatin1String("EditorPlugin")}, + {('E'), QLatin1String("EditorProperty")}, + {('E'), QLatin1String("EditorResourcePicker")}, + {('E'), QLatin1String("EditorResourcePreview")}, + {('E'), QLatin1String("EditorScriptPicker")}, + {('E'), QLatin1String("EditorSpinSlider")}, + {('F'), QLatin1String("FileDialog")}, + {('F'), QLatin1String("FileSystemDock")}, + {('F'), QLatin1String("FlowContainer")}, + {('F'), QLatin1String("FogVolume")}, + {('G'), QLatin1String("Generic6DOFJoint3D")}, + {('G'), QLatin1String("GeometryInstance3D")}, + {('G'), QLatin1String("GPUParticles2D")}, + {('G'), QLatin1String("GPUParticles3D")}, + {('G'), QLatin1String("GPUParticlesAttractor3D")}, + {('G'), QLatin1String("GPUParticlesAttractorBox3D")}, + {('G'), QLatin1String("GPUParticlesAttractorSphere3D")}, + {('G'), QLatin1String("GPUParticlesAttractorVectorField3D")}, + {('G'), QLatin1String("GPUParticlesCollision3D")}, + {('G'), QLatin1String("GPUParticlesCollisionBox3D")}, + {('G'), QLatin1String("GPUParticlesCollisionHeightField3D")}, + {('G'), QLatin1String("GPUParticlesCollisionSDF3D")}, + {('G'), QLatin1String("GPUParticlesCollisionSphere3D")}, + {('G'), QLatin1String("GraphEdit")}, + {('G'), QLatin1String("GraphElement")}, + {('G'), QLatin1String("GraphFrame")}, + {('G'), QLatin1String("GraphNode")}, + {('G'), QLatin1String("GridContainer")}, + {('G'), QLatin1String("GridMap")}, + {('G'), QLatin1String("GrooveJoint2D")}, + {('H'), QLatin1String("HBoxContainer")}, + {('H'), QLatin1String("HFlowContainer")}, + {('H'), QLatin1String("HingeJoint3D")}, + {('H'), QLatin1String("HScrollBar")}, + {('H'), QLatin1String("HSeparator")}, + {('H'), QLatin1String("HSlider")}, + {('H'), QLatin1String("HSplitContainer")}, + {('H'), QLatin1String("HTTPRequest")}, + {('I'), QLatin1String("ImporterMeshInstance3D")}, + {('I'), QLatin1String("InstancePlaceholder")}, + {('I'), QLatin1String("ItemList")}, + {('J'), QLatin1String("Joint2D")}, + {('J'), QLatin1String("Joint3D")}, + {('L'), QLatin1String("Label")}, + {('L'), QLatin1String("Label3D")}, + {('L'), QLatin1String("Light2D")}, + {('L'), QLatin1String("Light3D")}, + {('L'), QLatin1String("LightmapGI")}, + {('L'), QLatin1String("LightmapProbe")}, + {('L'), QLatin1String("LightOccluder2D")}, + {('L'), QLatin1String("Line2D")}, + {('L'), QLatin1String("LineEdit")}, + {('L'), QLatin1String("LinkButton")}, + {('M'), QLatin1String("MarginContainer")}, + {('M'), QLatin1String("Marker2D")}, + {('M'), QLatin1String("Marker3D")}, + {('M'), QLatin1String("MenuBar")}, + {('M'), QLatin1String("MenuButton")}, + {('M'), QLatin1String("MeshInstance2D")}, + {('M'), QLatin1String("MeshInstance3D")}, + {('M'), QLatin1String("MissingNode")}, + {('M'), QLatin1String("MultiMeshInstance2D")}, + {('M'), QLatin1String("MultiMeshInstance3D")}, + {('M'), QLatin1String("MultiplayerSpawner")}, + {('M'), QLatin1String("MultiplayerSynchronizer")}, + {('N'), QLatin1String("NavigationAgent2D")}, + {('N'), QLatin1String("NavigationAgent3D")}, + {('N'), QLatin1String("NavigationLink2D")}, + {('N'), QLatin1String("NavigationLink3D")}, + {('N'), QLatin1String("NavigationObstacle2D")}, + {('N'), QLatin1String("NavigationObstacle3D")}, + {('N'), QLatin1String("NavigationRegion2D")}, + {('N'), QLatin1String("NavigationRegion3D")}, + {('N'), QLatin1String("NinePatchRect")}, + {('N'), QLatin1String("Node2D")}, + {('N'), QLatin1String("Node3D")}, + {('O'), QLatin1String("OccluderInstance3D")}, + {('O'), QLatin1String("OmniLight3D")}, + {('O'), QLatin1String("OpenXRCompositionLayer")}, + {('O'), QLatin1String("OpenXRCompositionLayerCylinder")}, + {('O'), QLatin1String("OpenXRCompositionLayerEquirect")}, + {('O'), QLatin1String("OpenXRCompositionLayerQuad")}, + {('O'), QLatin1String("OpenXRHand")}, + {('O'), QLatin1String("OptionButton")}, + {('P'), QLatin1String("Panel")}, + {('P'), QLatin1String("PanelContainer")}, + {('P'), QLatin1String("Parallax2D")}, + {('P'), QLatin1String("ParallaxBackground")}, + {('P'), QLatin1String("ParallaxLayer")}, + {('P'), QLatin1String("Path2D")}, + {('P'), QLatin1String("Path3D")}, + {('P'), QLatin1String("PathFollow2D")}, + {('P'), QLatin1String("PathFollow3D")}, + {('P'), QLatin1String("PhysicalBone2D")}, + {('P'), QLatin1String("PhysicalBone3D")}, + {('P'), QLatin1String("PhysicalBoneSimulator3D")}, + {('P'), QLatin1String("PhysicsBody2D")}, + {('P'), QLatin1String("PhysicsBody3D")}, + {('P'), QLatin1String("PinJoint2D")}, + {('P'), QLatin1String("PinJoint3D")}, + {('P'), QLatin1String("PointLight2D")}, + {('P'), QLatin1String("Polygon2D")}, + {('P'), QLatin1String("Popup")}, + {('P'), QLatin1String("PopupMenu")}, + {('P'), QLatin1String("PopupPanel")}, + {('P'), QLatin1String("ProgressBar")}, + {('R'), QLatin1String("Range")}, + {('R'), QLatin1String("RayCast2D")}, + {('R'), QLatin1String("RayCast3D")}, + {('R'), QLatin1String("ReferenceRect")}, + {('R'), QLatin1String("ReflectionProbe")}, + {('R'), QLatin1String("RemoteTransform2D")}, + {('R'), QLatin1String("RemoteTransform3D")}, + {('R'), QLatin1String("ResourcePreloader")}, + {('R'), QLatin1String("RichTextLabel")}, + {('R'), QLatin1String("RigidBody2D")}, + {('R'), QLatin1String("RigidBody3D")}, + {('R'), QLatin1String("RootMotionView")}, + {('S'), QLatin1String("ScriptCreateDialog")}, + {('S'), QLatin1String("ScriptEditor")}, + {('S'), QLatin1String("ScriptEditorBase")}, + {('S'), QLatin1String("ScrollBar")}, + {('S'), QLatin1String("ScrollContainer")}, + {('S'), QLatin1String("Separator")}, + {('S'), QLatin1String("ShaderGlobalsOverride")}, + {('S'), QLatin1String("ShapeCast2D")}, + {('S'), QLatin1String("ShapeCast3D")}, + {('S'), QLatin1String("Skeleton2D")}, + {('S'), QLatin1String("Skeleton3D")}, + {('S'), QLatin1String("SkeletonIK3D")}, + {('S'), QLatin1String("SkeletonModifier3D")}, + {('S'), QLatin1String("Slider")}, + {('S'), QLatin1String("SliderJoint3D")}, + {('S'), QLatin1String("SoftBody3D")}, + {('S'), QLatin1String("SpinBox")}, + {('S'), QLatin1String("SplitContainer")}, + {('S'), QLatin1String("SpotLight3D")}, + {('S'), QLatin1String("SpringArm3D")}, + {('S'), QLatin1String("Sprite2D")}, + {('S'), QLatin1String("Sprite3D")}, + {('S'), QLatin1String("SpriteBase3D")}, + {('S'), QLatin1String("StaticBody2D")}, + {('S'), QLatin1String("StaticBody3D")}, + {('S'), QLatin1String("StatusIndicator")}, + {('S'), QLatin1String("SubViewport")}, + {('S'), QLatin1String("SubViewportContainer")}, + {('T'), QLatin1String("TabBar")}, + {('T'), QLatin1String("TabContainer")}, + {('T'), QLatin1String("TextEdit")}, + {('T'), QLatin1String("TextureButton")}, + {('T'), QLatin1String("TextureProgressBar")}, + {('T'), QLatin1String("TextureRect")}, + {('T'), QLatin1String("TileMap")}, + {('T'), QLatin1String("TileMapLayer")}, + {('T'), QLatin1String("Timer")}, + {('T'), QLatin1String("TouchScreenButton")}, + {('T'), QLatin1String("Tree")}, + {('V'), QLatin1String("VBoxContainer")}, + {('V'), QLatin1String("VehicleBody3D")}, + {('V'), QLatin1String("VehicleWheel3D")}, + {('V'), QLatin1String("VFlowContainer")}, + {('V'), QLatin1String("VideoStreamPlayer")}, + {('V'), QLatin1String("Viewport")}, + {('V'), QLatin1String("VisibleOnScreenEnabler2D")}, + {('V'), QLatin1String("VisibleOnScreenEnabler3D")}, + {('V'), QLatin1String("VisibleOnScreenNotifier2D")}, + {('V'), QLatin1String("VisibleOnScreenNotifier3D")}, + {('V'), QLatin1String("VisualInstance3D")}, + {('V'), QLatin1String("VoxelGI")}, + {('V'), QLatin1String("VScrollBar")}, + {('V'), QLatin1String("VSeparator")}, + {('V'), QLatin1String("VSlider")}, + {('V'), QLatin1String("VSplitContainer")}, + {('W'), QLatin1String("Window")}, + {('W'), QLatin1String("WorldEnvironment")}, + {('X'), QLatin1String("XRAnchor3D")}, + {('X'), QLatin1String("XRBodyModifier3D")}, + {('X'), QLatin1String("XRCamera3D")}, + {('X'), QLatin1String("XRController3D")}, + {('X'), QLatin1String("XRFaceModifier3D")}, + {('X'), QLatin1String("XRHandModifier3D")}, + {('X'), QLatin1String("XRNode3D")}, + {('X'), QLatin1String("XROrigin3D")}, + /* Resources */ + {('R'), QLatin1String("Resource")}, + {('A'), QLatin1String("AnimatedTexture")}, + {('A'), QLatin1String("Animation")}, + {('A'), QLatin1String("AnimationLibrary")}, + {('A'), QLatin1String("AnimationNode")}, + {('A'), QLatin1String("AnimationNodeAdd2")}, + {('A'), QLatin1String("AnimationNodeAdd3")}, + {('A'), QLatin1String("AnimationNodeAnimation")}, + {('A'), QLatin1String("AnimationNodeBlend2")}, + {('A'), QLatin1String("AnimationNodeBlend3")}, + {('A'), QLatin1String("AnimationNodeBlendSpace1D")}, + {('A'), QLatin1String("AnimationNodeBlendSpace2D")}, + {('A'), QLatin1String("AnimationNodeBlendTree")}, + {('A'), QLatin1String("AnimationNodeOneShot")}, + {('A'), QLatin1String("AnimationNodeOutput")}, + {('A'), QLatin1String("AnimationNodeStateMachine")}, + {('A'), QLatin1String("AnimationNodeStateMachinePlayback")}, + {('A'), QLatin1String("AnimationNodeStateMachineTransition")}, + {('A'), QLatin1String("AnimationNodeSub2")}, + {('A'), QLatin1String("AnimationNodeSync")}, + {('A'), QLatin1String("AnimationNodeTimeScale")}, + {('A'), QLatin1String("AnimationNodeTimeSeek")}, + {('A'), QLatin1String("AnimationNodeTransition")}, + {('A'), QLatin1String("AnimationRootNode")}, + {('A'), QLatin1String("ArrayMesh")}, + {('A'), QLatin1String("ArrayOccluder3D")}, + {('A'), QLatin1String("AtlasTexture")}, + {('A'), QLatin1String("AudioBusLayout")}, + {('A'), QLatin1String("AudioEffect")}, + {('A'), QLatin1String("AudioEffectAmplify")}, + {('A'), QLatin1String("AudioEffectBandLimitFilter")}, + {('A'), QLatin1String("AudioEffectBandPassFilter")}, + {('A'), QLatin1String("AudioEffectCapture")}, + {('A'), QLatin1String("AudioEffectChorus")}, + {('A'), QLatin1String("AudioEffectCompressor")}, + {('A'), QLatin1String("AudioEffectDelay")}, + {('A'), QLatin1String("AudioEffectDistortion")}, + {('A'), QLatin1String("AudioEffectEQ")}, + {('A'), QLatin1String("AudioEffectEQ10")}, + {('A'), QLatin1String("AudioEffectEQ21")}, + {('A'), QLatin1String("AudioEffectEQ6")}, + {('A'), QLatin1String("AudioEffectFilter")}, + {('A'), QLatin1String("AudioEffectHardLimiter")}, + {('A'), QLatin1String("AudioEffectHighPassFilter")}, + {('A'), QLatin1String("AudioEffectHighShelfFilter")}, + {('A'), QLatin1String("AudioEffectLimiter")}, + {('A'), QLatin1String("AudioEffectLowPassFilter")}, + {('A'), QLatin1String("AudioEffectLowShelfFilter")}, + {('A'), QLatin1String("AudioEffectNotchFilter")}, + {('A'), QLatin1String("AudioEffectPanner")}, + {('A'), QLatin1String("AudioEffectPhaser")}, + {('A'), QLatin1String("AudioEffectPitchShift")}, + {('A'), QLatin1String("AudioEffectRecord")}, + {('A'), QLatin1String("AudioEffectReverb")}, + {('A'), QLatin1String("AudioEffectSpectrumAnalyzer")}, + {('A'), QLatin1String("AudioEffectStereoEnhance")}, + {('A'), QLatin1String("AudioStream")}, + {('A'), QLatin1String("AudioStreamGenerator")}, + {('A'), QLatin1String("AudioStreamInteractive")}, + {('A'), QLatin1String("AudioStreamMicrophone")}, + {('A'), QLatin1String("AudioStreamMP3")}, + {('A'), QLatin1String("AudioStreamOggVorbis")}, + {('A'), QLatin1String("AudioStreamPlaylist")}, + {('A'), QLatin1String("AudioStreamPolyphonic")}, + {('A'), QLatin1String("AudioStreamRandomizer")}, + {('A'), QLatin1String("AudioStreamSynchronized")}, + {('A'), QLatin1String("AudioStreamWAV")}, + {('B'), QLatin1String("BaseMaterial3D")}, + {('B'), QLatin1String("BitMap")}, + {('B'), QLatin1String("BoneMap")}, + {('B'), QLatin1String("BoxMesh")}, + {('B'), QLatin1String("BoxOccluder3D")}, + {('B'), QLatin1String("BoxShape3D")}, + {('B'), QLatin1String("ButtonGroup")}, + {('C'), QLatin1String("CameraAttributes")}, + {('C'), QLatin1String("CameraAttributesPhysical")}, + {('C'), QLatin1String("CameraAttributesPractical")}, + {('C'), QLatin1String("CameraTexture")}, + {('C'), QLatin1String("CanvasItemMaterial")}, + {('C'), QLatin1String("CanvasTexture")}, + {('C'), QLatin1String("CapsuleMesh")}, + {('C'), QLatin1String("CapsuleShape2D")}, + {('C'), QLatin1String("CapsuleShape3D")}, + {('C'), QLatin1String("CircleShape2D")}, + {('C'), QLatin1String("CodeHighlighter")}, + {('C'), QLatin1String("Compositor")}, + {('C'), QLatin1String("CompositorEffect")}, + {('C'), QLatin1String("CompressedCubemap")}, + {('C'), QLatin1String("CompressedCubemapArray")}, + {('C'), QLatin1String("CompressedTexture2D")}, + {('C'), QLatin1String("CompressedTexture2DArray")}, + {('C'), QLatin1String("CompressedTexture3D")}, + {('C'), QLatin1String("CompressedTextureLayered")}, + {('C'), QLatin1String("ConcavePolygonShape2D")}, + {('C'), QLatin1String("ConcavePolygonShape3D")}, + {('C'), QLatin1String("ConvexPolygonShape2D")}, + {('C'), QLatin1String("ConvexPolygonShape3D")}, + {('C'), QLatin1String("CryptoKey")}, + {('C'), QLatin1String("CSharpScript")}, + {('C'), QLatin1String("Cubemap")}, + {('C'), QLatin1String("CubemapArray")}, + {('C'), QLatin1String("Curve")}, + {('C'), QLatin1String("Curve2D")}, + {('C'), QLatin1String("Curve3D")}, + {('C'), QLatin1String("CurveTexture")}, + {('C'), QLatin1String("CurveXYZTexture")}, + {('C'), QLatin1String("CylinderMesh")}, + {('C'), QLatin1String("CylinderShape3D")}, + {('E'), QLatin1String("EditorNode3DGizmoPlugin")}, + {('E'), QLatin1String("EditorSettings")}, + {('E'), QLatin1String("EditorSyntaxHighlighter")}, + {('E'), QLatin1String("Environment")}, + {('F'), QLatin1String("FastNoiseLite")}, + {('F'), QLatin1String("FBXDocument")}, + {('F'), QLatin1String("FBXState")}, + {('F'), QLatin1String("FogMaterial")}, + {('F'), QLatin1String("Font")}, + {('F'), QLatin1String("FontFile")}, + {('F'), QLatin1String("FontVariation")}, + {('G'), QLatin1String("GDExtension")}, + {('G'), QLatin1String("GDScript")}, + {('G'), QLatin1String("GLTFAccessor")}, + {('G'), QLatin1String("GLTFAnimation")}, + {('G'), QLatin1String("GLTFBufferView")}, + {('G'), QLatin1String("GLTFCamera")}, + {('G'), QLatin1String("GLTFDocument")}, + {('G'), QLatin1String("GLTFDocumentExtension")}, + {('G'), QLatin1String("GLTFDocumentExtensionConvertImporterMesh")}, + {('G'), QLatin1String("GLTFLight")}, + {('G'), QLatin1String("GLTFMesh")}, + {('G'), QLatin1String("GLTFNode")}, + {('G'), QLatin1String("GLTFPhysicsBody")}, + {('G'), QLatin1String("GLTFPhysicsShape")}, + {('G'), QLatin1String("GLTFSkeleton")}, + {('G'), QLatin1String("GLTFSkin")}, + {('G'), QLatin1String("GLTFSpecGloss")}, + {('G'), QLatin1String("GLTFState")}, + {('G'), QLatin1String("GLTFTexture")}, + {('G'), QLatin1String("GLTFTextureSampler")}, + {('G'), QLatin1String("Gradient")}, + {('G'), QLatin1String("GradientTexture1D")}, + {('G'), QLatin1String("GradientTexture2D")}, + {('H'), QLatin1String("HeightMapShape3D")}, + {('I'), QLatin1String("Image")}, + {('I'), QLatin1String("ImageTexture")}, + {('I'), QLatin1String("ImageTexture3D")}, + {('I'), QLatin1String("ImageTextureLayered")}, + {('I'), QLatin1String("ImmediateMesh")}, + {('I'), QLatin1String("ImporterMesh")}, + {('I'), QLatin1String("InputEvent")}, + {('I'), QLatin1String("InputEventAction")}, + {('I'), QLatin1String("InputEventFromWindow")}, + {('I'), QLatin1String("InputEventGesture")}, + {('I'), QLatin1String("InputEventJoyPadButton")}, + {('I'), QLatin1String("InputEventJoyPadMotion")}, + {('I'), QLatin1String("InputEventKey")}, + {('I'), QLatin1String("InputEventMagnifyGesture")}, + {('I'), QLatin1String("InputEventMIDI")}, + {('I'), QLatin1String("InputEventMouse")}, + {('I'), QLatin1String("InputEventMouseButton")}, + {('I'), QLatin1String("InputEventMouseMotion")}, + {('I'), QLatin1String("InputEventPanGesture")}, + {('I'), QLatin1String("InputEventScreenDrag")}, + {('I'), QLatin1String("InputEventScreenTouch")}, + {('I'), QLatin1String("InputEventShortcut")}, + {('I'), QLatin1String("InputEventWithModifiers")}, + {('J'), QLatin1String("JSON")}, + {('L'), QLatin1String("LabelSettings")}, + {('L'), QLatin1String("LightmapGIData")}, + {('M'), QLatin1String("Material")}, + {('M'), QLatin1String("Mesh")}, + {('M'), QLatin1String("MeshLibrary")}, + {('M'), QLatin1String("MeshTexture")}, + {('M'), QLatin1String("MisMeshsingResource")}, + {('M'), QLatin1String("MultiMesh")}, + {('N'), QLatin1String("NavigationMesh")}, + {('N'), QLatin1String("NavigationMeshSourceGeometryData2D")}, + {('N'), QLatin1String("NavigationMeshSourceGeometryData3D")}, + {('N'), QLatin1String("NavigationPolygon")}, + {('N'), QLatin1String("Noise")}, + {('N'), QLatin1String("NoiseTexture2D")}, + {('N'), QLatin1String("NoiseTexture3D")}, + {('O'), QLatin1String("Occluder3D")}, + {('O'), QLatin1String("OccluderPolygon2D")}, + {('O'), QLatin1String("OggPacketSequence")}, + {('O'), QLatin1String("OpenXRAction")}, + {('O'), QLatin1String("OpenXRActionMap")}, + {('O'), QLatin1String("OpenXRActionSet")}, + {('O'), QLatin1String("OpenXRInteractionProfile")}, + {('O'), QLatin1String("OpenXRIPBinding")}, + {('O'), QLatin1String("OptimizedTranslation")}, + {('O'), QLatin1String("ORMMaterial3D")}, + {('P'), QLatin1String("PackedDataContainer")}, + {('P'), QLatin1String("PackedScene")}, + {('P'), QLatin1String("PanoramaSkyMaterial")}, + {('P'), QLatin1String("ParticleProcessMaterial")}, + {('P'), QLatin1String("PhysicalSkyMaterial")}, + {('P'), QLatin1String("PhysicsMaterial")}, + {('P'), QLatin1String("PlaceholderCubemap")}, + {('P'), QLatin1String("PlaceholderCubemapArray")}, + {('P'), QLatin1String("PlaceholderMaterial")}, + {('P'), QLatin1String("PlaceholderMesh")}, + {('P'), QLatin1String("PlaceholderTexture2D")}, + {('P'), QLatin1String("PlaceholderTexture2DArray")}, + {('P'), QLatin1String("PlaceholderTexture3D")}, + {('P'), QLatin1String("PlaceholderTextureLayered")}, + {('P'), QLatin1String("PlaneMesh")}, + {('P'), QLatin1String("PointMesh")}, + {('P'), QLatin1String("PolygonOccluder3D")}, + {('P'), QLatin1String("PolygonPathFinder")}, + {('P'), QLatin1String("PortableCompressedTexture2D")}, + {('P'), QLatin1String("PrimitiveMesh")}, + {('P'), QLatin1String("PrismMesh")}, + {('P'), QLatin1String("ProceduralSkyMaterial")}, + {('Q'), QLatin1String("QuadMesh")}, + {('Q'), QLatin1String("QuadOccluder3D")}, + {('R'), QLatin1String("RDShaderFile")}, + {('R'), QLatin1String("RDShaderSPIRV")}, + {('R'), QLatin1String("RectangleShape2D")}, + {('R'), QLatin1String("RibbonTrailMesh")}, + {('R'), QLatin1String("RichTextEffect")}, + {('R'), QLatin1String("SceneReplicationConfig")}, + {('S'), QLatin1String("Script")}, + {('S'), QLatin1String("ScriptExtension")}, + {('S'), QLatin1String("SegmentShape2D")}, + {('S'), QLatin1String("SeparationRayShape2D")}, + {('S'), QLatin1String("SeparationRayShape3D")}, + {('S'), QLatin1String("Shader")}, + {('S'), QLatin1String("ShaderInclude")}, + {('S'), QLatin1String("ShaderMaterial")}, + {('S'), QLatin1String("Shape2D")}, + {('S'), QLatin1String("Shape3D")}, + {('S'), QLatin1String("Shortcut")}, + {('S'), QLatin1String("SkeletonModification2D")}, + {('S'), QLatin1String("SkeletonModification2DCCDIK")}, + {('S'), QLatin1String("SkeletonModification2DFABRIK")}, + {('S'), QLatin1String("SkeletonModification2DJiggle")}, + {('S'), QLatin1String("SkeletonModification2DLookAt")}, + {('S'), QLatin1String("SkeletonModification2DPhysicalBones")}, + {('S'), QLatin1String("SkeletonModification2DStackHolder")}, + {('S'), QLatin1String("SkeletonModification2DTwoBoneIK")}, + {('S'), QLatin1String("SkeletonModificationStack2D")}, + {('S'), QLatin1String("SkeletonProfile")}, + {('S'), QLatin1String("SkeletonProfileHumanoid")}, + {('S'), QLatin1String("Skin")}, + {('S'), QLatin1String("Sky")}, + {('S'), QLatin1String("SphereMesh")}, + {('S'), QLatin1String("SphereOccluder3D")}, + {('S'), QLatin1String("SphereShape3D")}, + {('S'), QLatin1String("SpriteFrames")}, + {('S'), QLatin1String("StandardMaterial3D")}, + {('S'), QLatin1String("StyleBox")}, + {('S'), QLatin1String("StyleBoxEmpty")}, + {('S'), QLatin1String("StyleBoxFlat")}, + {('S'), QLatin1String("StyleBoxLine")}, + {('S'), QLatin1String("StyleBoxTexture")}, + {('S'), QLatin1String("SystemFont")}, + {('T'), QLatin1String("TextMesh")}, + {('T'), QLatin1String("Texture")}, + {('T'), QLatin1String("Texture2D")}, + {('T'), QLatin1String("Texture2DArray")}, + {('T'), QLatin1String("Texture2DArrayRD")}, + {('T'), QLatin1String("Texture2DRD")}, + {('T'), QLatin1String("Texture3D")}, + {('T'), QLatin1String("Texture3DRD")}, + {('T'), QLatin1String("TextureCubemapArrayRD")}, + {('T'), QLatin1String("TextureCubemapRD")}, + {('T'), QLatin1String("TextureLayered")}, + {('T'), QLatin1String("TextureLayeredRD")}, + {('T'), QLatin1String("Theme")}, + {('T'), QLatin1String("TileMapPattern")}, + {('T'), QLatin1String("TileSet")}, + {('T'), QLatin1String("TileSetAtlasSource")}, + {('T'), QLatin1String("TileSetScenesCollectionSource")}, + {('T'), QLatin1String("TileSetSource")}, + {('T'), QLatin1String("TorusMesh")}, + {('T'), QLatin1String("Translation")}, + {('T'), QLatin1String("TubeTrailMesh")}, + {('V'), QLatin1String("VideoStream")}, + {('V'), QLatin1String("VideoStreamPlayback")}, + {('V'), QLatin1String("VideoStreamTheora")}, + {('V'), QLatin1String("ViewportTexture")}, + {('V'), QLatin1String("VisualShader")}, + {('V'), QLatin1String("VisualShaderNode")}, + {('V'), QLatin1String("VisualShaderNodeBillboard")}, + {('V'), QLatin1String("VisualShaderNodeBooleanConstant")}, + {('V'), QLatin1String("VisualShaderNodeBooleanParameter")}, + {('V'), QLatin1String("VisualShaderNodeClamp")}, + {('V'), QLatin1String("VisualShaderNodeColorConstant")}, + {('V'), QLatin1String("VisualShaderNodeColorFunc")}, + {('V'), QLatin1String("VisualShaderNodeColorOp")}, + {('V'), QLatin1String("VisualShaderNodeColorParameter")}, + {('V'), QLatin1String("VisualShaderNodeComment")}, + {('V'), QLatin1String("VisualShaderNodeCompare")}, + {('V'), QLatin1String("VisualShaderNodeConstant")}, + {('V'), QLatin1String("VisualShaderNodeCubemap")}, + {('V'), QLatin1String("VisualShaderNodeCubemapParameter")}, + {('V'), QLatin1String("VisualShaderNodeCurveTexture")}, + {('V'), QLatin1String("VisualShaderNodeCurveXYZTexture")}, + {('V'), QLatin1String("VisualShaderNodeCustom")}, + {('V'), QLatin1String("VisualShaderNodeDerivativeFunc")}, + {('V'), QLatin1String("VisualShaderNodeDeterminant")}, + {('V'), QLatin1String("VisualShaderNodeDistanceFade")}, + {('V'), QLatin1String("VisualShaderNodeDotProduct")}, + {('V'), QLatin1String("VisualShaderNodeExpression")}, + {('V'), QLatin1String("VisualShaderNodeFaceForward")}, + {('V'), QLatin1String("VisualShaderNodeFloatConstant")}, + {('V'), QLatin1String("VisualShaderNodeFloatFunc")}, + {('V'), QLatin1String("VisualShaderNodeFloatOp")}, + {('V'), QLatin1String("VisualShaderNodeFloatParameter")}, + {('V'), QLatin1String("VisualShaderNodeFrame")}, + {('V'), QLatin1String("VisualShaderNodeFresnel")}, + {('V'), QLatin1String("VisualShaderNodeGlobalExpression")}, + {('V'), QLatin1String("VisualShaderNodeGroupBase")}, + {('V'), QLatin1String("VisualShaderNodeIf")}, + {('V'), QLatin1String("VisualShaderNodeInput")}, + {('V'), QLatin1String("VisualShaderNodeIntConstant")}, + {('V'), QLatin1String("VisualShaderNodeIntFunc")}, + {('V'), QLatin1String("VisualShaderNodeIntOp")}, + {('V'), QLatin1String("VisualShaderNodeIntParameter")}, + {('V'), QLatin1String("VisualShaderNodeIs")}, + {('V'), QLatin1String("VisualShaderNodeLinearSceneDepth")}, + {('V'), QLatin1String("VisualShaderNodeMix")}, + {('V'), QLatin1String("VisualShaderNodeMultiplyAdd")}, + {('V'), QLatin1String("VisualShaderNodeOuterProduct")}, + {('V'), QLatin1String("VisualShaderNodeOutput")}, + {('V'), QLatin1String("VisualShaderNodeParameter")}, + {('V'), QLatin1String("VisualShaderNodeParameterRef")}, + {('V'), QLatin1String("VisualShaderNodeParticleAccelerator")}, + {('V'), QLatin1String("VisualShaderNodeParticleBoxEmitter")}, + {('V'), QLatin1String("VisualShaderNodeParticleConeVelocity")}, + {('V'), QLatin1String("VisualShaderNodeParticleEmit")}, + {('V'), QLatin1String("VisualShaderNodeParticleEmitter")}, + {('V'), QLatin1String("VisualShaderNodeParticleMeshEmitter")}, + {('V'), QLatin1String("VisualShaderNodeParticleMultiplyByAxisAngle")}, + {('V'), QLatin1String("VisualShaderNodeParticleOutput")}, + {('V'), QLatin1String("VisualShaderNodeParticleRandomness")}, + {('V'), QLatin1String("VisualShaderNodeParticleRingEmitter")}, + {('V'), QLatin1String("VisualShaderNodeParticleSphereEmitter")}, + {('V'), QLatin1String("VisualShaderNodeProximityFade")}, + {('V'), QLatin1String("VisualShaderNodeRandomRange")}, + {('V'), QLatin1String("VisualShaderNodeRemap")}, + {('V'), QLatin1String("VisualShaderNodeReroute")}, + {('V'), QLatin1String("VisualShaderNodeResizableBase")}, + {('V'), QLatin1String("VisualShaderNodeRotationByAxis")}, + {('V'), QLatin1String("VisualShaderNodeSample3D")}, + {('V'), QLatin1String("VisualShaderNodeScreenNormalWorldSpace")}, + {('V'), QLatin1String("VisualShaderNodeScreenUVToSDF")}, + {('V'), QLatin1String("VisualShaderNodeSDFRaymarch")}, + {('V'), QLatin1String("VisualShaderNodeSDFToScreenUV")}, + {('V'), QLatin1String("VisualShaderNodeSmoothStep")}, + {('V'), QLatin1String("VisualShaderNodeStep")}, + {('V'), QLatin1String("VisualShaderNodeSwitch")}, + {('V'), QLatin1String("VisualShaderNodeTexture")}, + {('V'), QLatin1String("VisualShaderNodeTexture2DArray")}, + {('V'), QLatin1String("VisualShaderNodeTexture2DArrayParameter")}, + {('V'), QLatin1String("VisualShaderNodeTexture2DParameter")}, + {('V'), QLatin1String("VisualShaderNodeTexture3D")}, + {('V'), QLatin1String("VisualShaderNodeTexture3DParameter")}, + {('V'), QLatin1String("VisualShaderNodeTextureParameter")}, + {('V'), QLatin1String("VisualShaderNodeTextureParameterTriplanar")}, + {('V'), QLatin1String("VisualShaderNodeTextureSDF")}, + {('V'), QLatin1String("VisualShaderNodeTextureSDFNormal")}, + {('V'), QLatin1String("VisualShaderNodeTransformCompose")}, + {('V'), QLatin1String("VisualShaderNodeTransformConstant")}, + {('V'), QLatin1String("VisualShaderNodeTransformDecompose")}, + {('V'), QLatin1String("VisualShaderNodeTransformFunc")}, + {('V'), QLatin1String("VisualShaderNodeTransformOp")}, + {('V'), QLatin1String("VisualShaderNodeTransformParameter")}, + {('V'), QLatin1String("VisualShaderNodeTransformVecMult")}, + {('V'), QLatin1String("VisualShaderNodeUIntConstant")}, + {('V'), QLatin1String("VisualShaderNodeUIntFunc")}, + {('V'), QLatin1String("VisualShaderNodeUIntOp")}, + {('V'), QLatin1String("VisualShaderNodeUIntParameter")}, + {('V'), QLatin1String("VisualShaderNodeUVFunc")}, + {('V'), QLatin1String("VisualShaderNodeUVPolarCoord")}, + {('V'), QLatin1String("VisualShaderNodeVarying")}, + {('V'), QLatin1String("VisualShaderNodeVaryingGetter")}, + {('V'), QLatin1String("VisualShaderNodeVaryingSetter")}, + {('V'), QLatin1String("VisualShaderNodeVec2Constant")}, + {('V'), QLatin1String("VisualShaderNodeVec2Parameter")}, + {('V'), QLatin1String("VisualShaderNodeVec3Constant")}, + {('V'), QLatin1String("VisualShaderNodeVec3Parameter")}, + {('V'), QLatin1String("VisualShaderNodeVec4Constant")}, + {('V'), QLatin1String("VisualShaderNodeVec4Parameter")}, + {('V'), QLatin1String("VisualShaderNodeVectorBase")}, + {('V'), QLatin1String("VisualShaderNodeVectorCompose")}, + {('V'), QLatin1String("VisualShaderNodeVectorDecompose")}, + {('V'), QLatin1String("VisualShaderNodeVectorDistance")}, + {('V'), QLatin1String("VisualShaderNodeVectorFunc")}, + {('V'), QLatin1String("VisualShaderNodeVectorLen")}, + {('V'), QLatin1String("VisualShaderNodeVectorOp")}, + {('V'), QLatin1String("VisualShaderNodeVectorRefract")}, + {('V'), QLatin1String("VisualShaderNodeWorldPositionFromDepth")}, + {('V'), QLatin1String("VoxelGIData")}, + {('W'), QLatin1String("World2D")}, + {('W'), QLatin1String("World3D")}, + {('W'), QLatin1String("WorldBoundaryShape2D")}, + {('W'), QLatin1String("WorldBoundaryShape3D")}, + {('X'), QLatin1String("X509Certificate")}, + /* Other objects */ + {('A'), QLatin1String("AESContext")}, + {('A'), QLatin1String("AStar2D")}, + {('A'), QLatin1String("AStar3D")}, + {('A'), QLatin1String("AStarGrid2D")}, + {('A'), QLatin1String("AudioEffectInstance")}, + {('A'), QLatin1String("AudioEffectSpectrumAnalyzerInstance")}, + {('A'), QLatin1String("AudioSample")}, + {('A'), QLatin1String("AudioSamplePlayback")}, + {('A'), QLatin1String("AudioServer")}, + {('A'), QLatin1String("AudioStreamGeneratorPlayback")}, + {('A'), QLatin1String("AudioStreamPlayback")}, + {('A'), QLatin1String("AudioStreamPlaybackInteractive")}, + {('A'), QLatin1String("AudioStreamPlaybackOggVorbis")}, + {('A'), QLatin1String("AudioStreamPlaybackPlaylist")}, + {('A'), QLatin1String("AudioStreamPlaybackPolyphonic")}, + {('A'), QLatin1String("AudioStreamPlaybackResampled")}, + {('A'), QLatin1String("AudioStreamPlaybackSynchronized")}, + {('C'), QLatin1String("CallbackTweener")}, + {('C'), QLatin1String("CameraFeed")}, + {('C'), QLatin1String("CameraServer")}, + {('C'), QLatin1String("CharFXTransform")}, + {('C'), QLatin1String("ClassDB")}, + {('C'), QLatin1String("ConfigFile")}, + {('C'), QLatin1String("Crypto")}, + {('D'), QLatin1String("DirAccess")}, + {('D'), QLatin1String("DisplayServer")}, + {('D'), QLatin1String("DTLSServer")}, + {('E'), QLatin1String("EditorDebuggerPlugin")}, + {('E'), QLatin1String("EditorDebuggerSession")}, + {('E'), QLatin1String("EditorExportPlatform")}, + {('E'), QLatin1String("EditorExportPlatformAndroid")}, + {('E'), QLatin1String("EditorExportPlatformIOS")}, + {('E'), QLatin1String("EditorExportPlatformLinuxBSD")}, + {('E'), QLatin1String("EditorExportPlatformMacOS")}, + {('E'), QLatin1String("EditorExportPlatformPC")}, + {('E'), QLatin1String("EditorExportPlatformWeb")}, + {('E'), QLatin1String("EditorExportPlatformWindows")}, + {('E'), QLatin1String("EditorExportPlugin")}, + {('E'), QLatin1String("EditorFeatureProfile")}, + {('E'), QLatin1String("EditorFileSystemDirectory")}, + {('E'), QLatin1String("EditorFileSystemImportFormatSupportQuery")}, + {('E'), QLatin1String("EditorImportPlugin")}, + {('E'), QLatin1String("EditorInspectorPlugin")}, + {('E'), QLatin1String("EditorInterface")}, + {('E'), QLatin1String("EditorNode3DGizmo")}, + {('E'), QLatin1String("EditorPaths")}, + {('E'), QLatin1String("EditorResourceConversionPlugin")}, + {('E'), QLatin1String("EditorResourcePreviewGenerator")}, + {('E'), QLatin1String("EditorResourceTooltipPlugin")}, + {('E'), QLatin1String("EditorSceneFormatImporter")}, + {('E'), QLatin1String("EditorSceneFormatImporterBlend")}, + {('E'), QLatin1String("EditorSceneFormatImporterFBX2GLTF")}, + {('E'), QLatin1String("EditorSceneFormatImporterGLTF")}, + {('E'), QLatin1String("EditorSceneFormatImporterUFBX")}, + {('E'), QLatin1String("EditorScenePostImport")}, + {('E'), QLatin1String("EditorScenePostImportPlugin")}, + {('E'), QLatin1String("EditorScript")}, + {('E'), QLatin1String("EditorSelection")}, + {('E'), QLatin1String("EditorTranslationParserPlugin")}, + {('E'), QLatin1String("EditorUndoRedoManager")}, + {('E'), QLatin1String("EditorVCSInterface")}, + {('E'), QLatin1String("EncodedObjectAsID")}, + {('E'), QLatin1String("ENetConnection")}, + {('E'), QLatin1String("ENetMultiplayerPeer")}, + {('E'), QLatin1String("ENetPacketPeer")}, + {('E'), QLatin1String("Engine")}, + {('E'), QLatin1String("EngineDebugger")}, + {('E'), QLatin1String("EngineProfiler")}, + {('E'), QLatin1String("Expression")}, + {('F'), QLatin1String("FileAccess")}, + {('F'), QLatin1String("FramebufferCacheRD")}, + {('G'), QLatin1String("GDExtensionManager")}, + {('G'), QLatin1String("Geometry2D")}, + {('G'), QLatin1String("Geometry3D")}, + {('H'), QLatin1String("HashingContext")}, + {('H'), QLatin1String("HMACContext")}, + {('H'), QLatin1String("HTTPClient")}, + {('I'), QLatin1String("ImageFormatLoader")}, + {('I'), QLatin1String("ImageFormatLoaderExtension")}, + {('I'), QLatin1String("Input")}, + {('I'), QLatin1String("InputMap")}, + {('I'), QLatin1String("IntervalTweener")}, + {('I'), QLatin1String("IP")}, + {('J'), QLatin1String("JavaClass")}, + {('J'), QLatin1String("JavaClassWrapper")}, + {('J'), QLatin1String("JavaScriptBridge")}, + {('J'), QLatin1String("JavaScriptObject")}, + {('J'), QLatin1String("JNISingleton")}, + {('J'), QLatin1String("JSONRPC")}, + {('K'), QLatin1String("KinematicCollision2D")}, + {('K'), QLatin1String("KinematicCollision3D")}, + {('L'), QLatin1String("Lightmapper")}, + {('L'), QLatin1String("LightmapperRD")}, + {('M'), QLatin1String("MainLoop")}, + {('M'), QLatin1String("Marshalls")}, + {('M'), QLatin1String("MeshConvexDecompositionSettings")}, + {('M'), QLatin1String("MeshDataTool")}, + {('M'), QLatin1String("MethodTweener")}, + {('M'), QLatin1String("MobileVRInterface")}, + {('M'), QLatin1String("MovieWriter")}, + {('M'), QLatin1String("MultiplayerAPI")}, + {('M'), QLatin1String("MultiplayerAPIExtension")}, + {('M'), QLatin1String("MultiplayerPeer")}, + {('M'), QLatin1String("MultiplayerPeerExtension")}, + {('M'), QLatin1String("Mutex")}, + {('N'), QLatin1String("NativeMenu")}, + {('N'), QLatin1String("NavigationMeshGenerator")}, + {('N'), QLatin1String("NavigationPathQueryParameters2D")}, + {('N'), QLatin1String("NavigationPathQueryParameters3D")}, + {('N'), QLatin1String("NavigationPathQueryResult2D")}, + {('N'), QLatin1String("NavigationPathQueryResult3D")}, + {('N'), QLatin1String("NavigationServer2D")}, + {('N'), QLatin1String("NavigationServer3D")}, + {('N'), QLatin1String("Node")}, + {('N'), QLatin1String("Node3DGizmo")}, + {('O'), QLatin1String("OfflineMultiplayerPeer")}, + {('O'), QLatin1String("OggPacketSequencePlayback")}, + {('O'), QLatin1String("OpenXRAPIExtension")}, + {('O'), QLatin1String("OpenXRExtensionWrapperExtension")}, + {('O'), QLatin1String("OpenXRInteractionProfileMetadata")}, + {('O'), QLatin1String("OpenXRInterface")}, + {('O'), QLatin1String("OS")}, + {('P'), QLatin1String("PackedDataContainerRef")}, + {('P'), QLatin1String("PacketPeer")}, + {('P'), QLatin1String("PacketPeerDTLS")}, + {('P'), QLatin1String("PacketPeerExtension")}, + {('P'), QLatin1String("PacketPeerStream")}, + {('P'), QLatin1String("PacketPeerUDP")}, + {('P'), QLatin1String("PCKPacker")}, + {('P'), QLatin1String("Performance")}, + {('P'), QLatin1String("PhysicsDirectBodyState2D")}, + {('P'), QLatin1String("PhysicsDirectBodyState2DExtension")}, + {('P'), QLatin1String("PhysicsDirectBodyState3D")}, + {('P'), QLatin1String("PhysicsDirectBodyState3DExtension")}, + {('P'), QLatin1String("PhysicsDirectSpaceState2D")}, + {('P'), QLatin1String("PhysicsDirectSpaceState2DExtension")}, + {('P'), QLatin1String("PhysicsDirectSpaceState3D")}, + {('P'), QLatin1String("PhysicsDirectSpaceState3DExtension")}, + {('P'), QLatin1String("PhysicsPointQueryParameters2D")}, + {('P'), QLatin1String("PhysicsPointQueryParameters3D")}, + {('P'), QLatin1String("PhysicsRayQueryParameters2D")}, + {('P'), QLatin1String("PhysicsRayQueryParameters3D")}, + {('P'), QLatin1String("PhysicsServer2D")}, + {('P'), QLatin1String("PhysicsServer2DExtension")}, + {('P'), QLatin1String("PhysicsServer2DManager")}, + {('P'), QLatin1String("PhysicsServer3D")}, + {('P'), QLatin1String("PhysicsServer3DExtension")}, + {('P'), QLatin1String("PhysicsServer3DManager")}, + {('P'), QLatin1String("PhysicsServer3DRenderingServerHandler")}, + {('P'), QLatin1String("PhysicsShapeQueryParameters2D")}, + {('P'), QLatin1String("PhysicsShapeQueryParameters3D")}, + {('P'), QLatin1String("PhysicsTestMotionParameters2D")}, + {('P'), QLatin1String("PhysicsTestMotionParameters3D")}, + {('P'), QLatin1String("PhysicsTestMotionResult2D")}, + {('P'), QLatin1String("PhysicsTestMotionResult3D")}, + {('P'), QLatin1String("ProjectSettings")}, + {('X'), QLatin1String("PropertyTweener")}, + {('R'), QLatin1String("RandomNumberGenerator")}, + {('R'), QLatin1String("RDAttachmentFormat")}, + {('R'), QLatin1String("RDFramebufferPass")}, + {('R'), QLatin1String("RDPipelineColorBlendState")}, + {('R'), QLatin1String("RDPipelineColorBlendStateAttachment")}, + {('R'), QLatin1String("RDPipelineDepthStencilState")}, + {('R'), QLatin1String("RDPipelineMultisampleState")}, + {('R'), QLatin1String("RDPipelineRasterizationState")}, + {('R'), QLatin1String("RDPipelineSpecializationConstant")}, + {('R'), QLatin1String("RDSamplerState")}, + {('R'), QLatin1String("RDShaderSource")}, + {('R'), QLatin1String("RDTextureFormat")}, + {('R'), QLatin1String("RDTextureView")}, + {('R'), QLatin1String("RDUniform")}, + {('R'), QLatin1String("RDVertexAttribute")}, + {('R'), QLatin1String("RefCounted")}, + {('R'), QLatin1String("RegEx")}, + {('R'), QLatin1String("RegExMatch")}, + {('R'), QLatin1String("RenderData")}, + {('R'), QLatin1String("RenderDataExtension")}, + {('R'), QLatin1String("RenderDataRD")}, + {('R'), QLatin1String("RenderingDevice")}, + {('R'), QLatin1String("RenderingServer")}, + {('R'), QLatin1String("RenderSceneBuffers")}, + {('R'), QLatin1String("RenderSceneBuffersConfiguration")}, + {('R'), QLatin1String("RenderSceneBuffersExtension")}, + {('R'), QLatin1String("RenderSceneBuffersRD")}, + {('R'), QLatin1String("RenderSceneData")}, + {('R'), QLatin1String("RenderSceneDataExtension")}, + {('R'), QLatin1String("RenderSceneDataRD")}, + {('R'), QLatin1String("Resource")}, + {('R'), QLatin1String("ResourceFormatLoader")}, + {('R'), QLatin1String("ResourceFormatSaver")}, + {('R'), QLatin1String("ResourceImporter")}, + {('R'), QLatin1String("ResourceImporterBitMap")}, + {('R'), QLatin1String("ResourceImporterBMFont")}, + {('R'), QLatin1String("ResourceImporterCSVTranslation")}, + {('R'), QLatin1String("ResourceImporterDynamicFont")}, + {('R'), QLatin1String("ResourceImporterImage")}, + {('R'), QLatin1String("ResourceImporterImageFont")}, + {('R'), QLatin1String("ResourceImporterLayeredTexture")}, + {('R'), QLatin1String("ResourceImporterMP3")}, + {('R'), QLatin1String("ResourceImporterOBJ")}, + {('R'), QLatin1String("ResourceImporterOggVorbis")}, + {('R'), QLatin1String("ResourceImporterScene")}, + {('R'), QLatin1String("ResourceImporterShaderFile")}, + {('R'), QLatin1String("ResourceImporterTexture")}, + {('R'), QLatin1String("ResourceImporterTextureAtlas")}, + {('R'), QLatin1String("ResourceImporterWAV")}, + {('R'), QLatin1String("ResourceLoader")}, + {('R'), QLatin1String("ResourceSaver")}, + {('R'), QLatin1String("ResourceUID")}, + {('S'), QLatin1String("SceneMultiplayer")}, + {('S'), QLatin1String("SceneState")}, + {('S'), QLatin1String("SceneTree")}, + {('S'), QLatin1String("SceneTreeTimer")}, + {('S'), QLatin1String("ScriptLanguage")}, + {('S'), QLatin1String("ScriptLanguageExtension")}, + {('S'), QLatin1String("Semaphore")}, + {('S'), QLatin1String("SkinReference")}, + {('S'), QLatin1String("StreamPeer")}, + {('S'), QLatin1String("StreamPeerBuffer")}, + {('S'), QLatin1String("StreamPeerExtension")}, + {('S'), QLatin1String("StreamPeerGZIP")}, + {('S'), QLatin1String("StreamPeerTCP")}, + {('S'), QLatin1String("StreamPeerTLS")}, + {('S'), QLatin1String("SurfaceTool")}, + {('T'), QLatin1String("TCPServer")}, + {('T'), QLatin1String("TextLine")}, + {('T'), QLatin1String("TextParagraph")}, + {('T'), QLatin1String("TextServer")}, + {('T'), QLatin1String("TextServerAdvanced")}, + {('T'), QLatin1String("TextServerDummy")}, + {('T'), QLatin1String("TextServerExtension")}, + {('T'), QLatin1String("TextServerFallback")}, + {('T'), QLatin1String("TextServerManager")}, + {('T'), QLatin1String("ThemeDB")}, + {('T'), QLatin1String("Thread")}, + {('T'), QLatin1String("TileData")}, + {('T'), QLatin1String("Time")}, + {('T'), QLatin1String("TLSOptions")}, + {('T'), QLatin1String("TranslationServer")}, + {('T'), QLatin1String("TreeItem")}, + {('T'), QLatin1String("TriangleMesh")}, + {('T'), QLatin1String("Tween")}, + {('T'), QLatin1String("Tweener")}, + {('U'), QLatin1String("UDPServer")}, + {('U'), QLatin1String("UndoRedo")}, + {('U'), QLatin1String("UniformSetCacheRD")}, + {('U'), QLatin1String("UPNP")}, + {('U'), QLatin1String("UPNPDevice")}, + {('W'), QLatin1String("WeakRef")}, + {('W'), QLatin1String("WebRTCDataChannel")}, + {('W'), QLatin1String("WebRTCDataChannelExtension")}, + {('W'), QLatin1String("WebRTCMultiplayerPeer")}, + {('W'), QLatin1String("WebRTCPeerConnection")}, + {('W'), QLatin1String("WebRTCPeerConnectionExtension")}, + {('W'), QLatin1String("WebSocketMultiplayerPeer")}, + {('W'), QLatin1String("WebSocketPeer")}, + {('W'), QLatin1String("WebXRInterface")}, + {('W'), QLatin1String("WorkerThreadPool")}, + {('X'), QLatin1String("XMLParser")}, + {('X'), QLatin1String("XRBodyTracker")}, + {('X'), QLatin1String("XRControllerTracker")}, + {('X'), QLatin1String("XRFaceTracker")}, + {('X'), QLatin1String("XRHandTracker")}, + {('X'), QLatin1String("XRInterface")}, + {('X'), QLatin1String("XRInterfaceExtension")}, + {('X'), QLatin1String("XRPose")}, + {('X'), QLatin1String("XRPositionalTracker")}, + {('X'), QLatin1String("XRServer")}, + {('X'), QLatin1String("XRTracker")}, + {('X'), QLatin1String("XRVRS")}, + {('Z'), QLatin1String("ZIPPacker")}, + {('Z'), QLatin1String("ZIPReader")}, + /* Editor only */ + {('E'), QLatin1String("EditorCommandPalette")}, + {('E'), QLatin1String("EditorDebuggerPlugin")}, + {('E'), QLatin1String("EditorDebuggerSession")}, + {('E'), QLatin1String("EditorExportPlatform")}, + {('E'), QLatin1String("EditorExportPlatformAndroid")}, + {('E'), QLatin1String("EditorExportPlatformIOS")}, + {('E'), QLatin1String("EditorExportPlatformLinuxBSD")}, + {('E'), QLatin1String("EditorExportPlatformMacOS")}, + {('E'), QLatin1String("EditorExportPlatformPC")}, + {('E'), QLatin1String("EditorExportPlatformWeb")}, + {('E'), QLatin1String("EditorExportPlatformWindows")}, + {('E'), QLatin1String("EditorExportPlugin")}, + {('E'), QLatin1String("EditorFeatureProfile")}, + {('E'), QLatin1String("EditorFileDialog")}, + {('E'), QLatin1String("EditorFileSystem")}, + {('E'), QLatin1String("EditorFileSystemDirectory")}, + {('E'), QLatin1String("EditorFileSystemImportFormatSupportQuery")}, + {('E'), QLatin1String("EditorImportPlugin")}, + {('E'), QLatin1String("EditorInspector")}, + {('E'), QLatin1String("EditorInspectorPlugin")}, + {('E'), QLatin1String("EditorInterface")}, + {('E'), QLatin1String("EditorNode3DGizmo")}, + {('E'), QLatin1String("EditorNode3DGizmoPlugin")}, + {('E'), QLatin1String("EditorPaths")}, + {('E'), QLatin1String("EditorPlugin")}, + {('E'), QLatin1String("EditorProperty")}, + {('E'), QLatin1String("EditorResourceConversionPlugin")}, + {('E'), QLatin1String("EditorResourcePicker")}, + {('E'), QLatin1String("EditorResourcePreview")}, + {('E'), QLatin1String("EditorResourcePreviewGenerator")}, + {('E'), QLatin1String("EditorResourceTooltipPlugin")}, + {('E'), QLatin1String("EditorSceneFormatImporter")}, + {('E'), QLatin1String("EditorSceneFormatImporterBlend")}, + {('E'), QLatin1String("EditorSceneFormatImporterFBX2GLTF")}, + {('E'), QLatin1String("EditorSceneFormatImporterGLTF")}, + {('E'), QLatin1String("EditorSceneFormatImporterUFBX")}, + {('E'), QLatin1String("EditorScenePostImport")}, + {('E'), QLatin1String("EditorScenePostImportPlugin")}, + {('E'), QLatin1String("EditorScript")}, + {('E'), QLatin1String("EditorScriptPicker")}, + {('E'), QLatin1String("EditorSelection")}, + {('E'), QLatin1String("EditorSettings")}, + {('E'), QLatin1String("EditorSpinSlider")}, + {('E'), QLatin1String("EditorSyntaxHighlighter")}, + {('E'), QLatin1String("EditorTranslationParserPlugin")}, + {('E'), QLatin1String("EditorUndoRedoManager")}, + {('E'), QLatin1String("EditorVCSInterface")}, + {('F'), QLatin1String("FileSystemDock")}, + {('S'), QLatin1String("ScriptCreateDialog")}, + {('S'), QLatin1String("ScriptEditor")}, + {('S'), QLatin1String("ScriptEditorBase")}, + }; + + gdscript_literals = { + {('n'), QLatin1String("null")}, + {('f'), QLatin1String("false")}, + {('t'), QLatin1String("true")}, + }; + + gdscript_builtin = { + /* @GDScript */ + {('C'), QLatin1String("Color8")}, + {('a'), QLatin1String("assert")}, + {('c'), QLatin1String("char")}, + {('c'), QLatin1String("convert")}, + {('d'), QLatin1String("dict_to_inst")}, + {('g'), QLatin1String("get_stack")}, + {('i'), QLatin1String("inst_to_dict")}, + {('i'), QLatin1String("is_instance_of")}, + {('l'), QLatin1String("len")}, + {('l'), QLatin1String("load")}, + {('p'), QLatin1String("preload")}, + {('p'), QLatin1String("print_debug")}, + {('p'), QLatin1String("print_stack")}, + {('r'), QLatin1String("range")}, + {('t'), QLatin1String("type_exists")}, + /* @GlobalScope */ + {('a'), QLatin1String("abs")}, + {('a'), QLatin1String("absf")}, + {('a'), QLatin1String("absi")}, + {('a'), QLatin1String("acos")}, + {('a'), QLatin1String("acosh")}, + {('a'), QLatin1String("angle_difference")}, + {('a'), QLatin1String("asin")}, + {('a'), QLatin1String("asinh")}, + {('a'), QLatin1String("atan")}, + {('a'), QLatin1String("atan2")}, + {('a'), QLatin1String("atanh")}, + {('b'), QLatin1String("bezier_derivative")}, + {('b'), QLatin1String("bezier_interpolate")}, + {('b'), QLatin1String("bytes_to_var")}, + {('b'), QLatin1String("bytes_to_var_with_objects")}, + {('c'), QLatin1String("ceil")}, + {('c'), QLatin1String("ceilf")}, + {('c'), QLatin1String("ceili")}, + {('c'), QLatin1String("clamp")}, + {('c'), QLatin1String("clampf")}, + {('c'), QLatin1String("clampi")}, + {('c'), QLatin1String("cos")}, + {('c'), QLatin1String("cosh")}, + {('c'), QLatin1String("cubic_interpolate")}, + {('c'), QLatin1String("cubic_interpolate_angle")}, + {('c'), QLatin1String("cubic_interpolate_angle_in_time")}, + {('c'), QLatin1String("cubic_interpolate_in_time")}, + {('d'), QLatin1String("db_to_linear")}, + {('d'), QLatin1String("deg_to_rad")}, + {('e'), QLatin1String("ease")}, + {('e'), QLatin1String("error_string")}, + {('e'), QLatin1String("exp")}, + {('f'), QLatin1String("floor")}, + {('f'), QLatin1String("floorf")}, + {('f'), QLatin1String("floori")}, + {('f'), QLatin1String("fmod")}, + {('f'), QLatin1String("fposmod")}, + {('h'), QLatin1String("hash")}, + {('i'), QLatin1String("instance_from_id")}, + {('i'), QLatin1String("inverse_lerp")}, + {('i'), QLatin1String("is_equal_approx")}, + {('i'), QLatin1String("is_finite")}, + {('i'), QLatin1String("is_inf")}, + {('i'), QLatin1String("is_instance_id_valid")}, + {('i'), QLatin1String("is_instance_valqual_approxid")}, + {('i'), QLatin1String("is_nan")}, + {('i'), QLatin1String("is_same")}, + {('i'), QLatin1String("is_zero_approx")}, + {('l'), QLatin1String("lerp")}, + {('l'), QLatin1String("lerp_angle")}, + {('l'), QLatin1String("lerpf")}, + {('l'), QLatin1String("linear_to_db")}, + {('l'), QLatin1String("log")}, + {('m'), QLatin1String("max")}, + {('m'), QLatin1String("maxf")}, + {('m'), QLatin1String("maxi")}, + {('m'), QLatin1String("min")}, + {('m'), QLatin1String("minf")}, + {('m'), QLatin1String("mini")}, + {('m'), QLatin1String("move_toward")}, + {('n'), QLatin1String("nearest_po2")}, + {('p'), QLatin1String("pingpong")}, + {('p'), QLatin1String("posmod")}, + {('p'), QLatin1String("pow")}, + {('p'), QLatin1String("print")}, + {('p'), QLatin1String("print_rich")}, + {('p'), QLatin1String("print_verbose")}, + {('p'), QLatin1String("printerr")}, + {('p'), QLatin1String("printraw")}, + {('p'), QLatin1String("prints")}, + {('p'), QLatin1String("printt")}, + {('p'), QLatin1String("push_error")}, + {('p'), QLatin1String("push_warning")}, + {('r'), QLatin1String("rad_to_deg")}, + {('r'), QLatin1String("rand_from_seed")}, + {('r'), QLatin1String("rand")}, + {('r'), QLatin1String("randf")}, + {('r'), QLatin1String("randf_range")}, + {('r'), QLatin1String("randfn")}, + {('r'), QLatin1String("randi")}, + {('r'), QLatin1String("randi_range")}, + {('r'), QLatin1String("randomize")}, + {('r'), QLatin1String("remap")}, + {('r'), QLatin1String("rid_allocate_id")}, + {('r'), QLatin1String("rid_from_int64")}, + {('r'), QLatin1String("rotate_toward")}, + {('r'), QLatin1String("round")}, + {('r'), QLatin1String("roundf")}, + {('r'), QLatin1String("roundi")}, + {('s'), QLatin1String("seed")}, + {('s'), QLatin1String("sign")}, + {('s'), QLatin1String("signf")}, + {('s'), QLatin1String("signi")}, + {('s'), QLatin1String("sin")}, + {('s'), QLatin1String("sinh")}, + {('s'), QLatin1String("smoothstep")}, + {('s'), QLatin1String("snapped")}, + {('s'), QLatin1String("snappedf")}, + {('s'), QLatin1String("snappedi")}, + {('s'), QLatin1String("sqrt")}, + {('s'), QLatin1String("step_decimals")}, + {('s'), QLatin1String("str")}, + {('t'), QLatin1String("tan")}, + {('t'), QLatin1String("tanh")}, + {('t'), QLatin1String("type_convert")}, + {('t'), QLatin1String("type_string")}, + {('t'), QLatin1String("typeof")}, + {('v'), QLatin1String("var_to_bytes")}, + {('v'), QLatin1String("var_to_bytes_with_objects")}, + {('v'), QLatin1String("var_to_str")}, + {('w'), QLatin1String("weakref")}, + {('w'), QLatin1String("wrap")}, + {('w'), QLatin1String("wrapf")}, + {('w'), QLatin1String("wrapi")}, + }; + + gdscript_other = { + {('e'), QLatin1String("export")}, + {('e'), QLatin1String("export_category")}, + {('e'), QLatin1String("export_color_no_alpha")}, + {('e'), QLatin1String("export_custom")}, + {('e'), QLatin1String("export_dir")}, + {('e'), QLatin1String("export_enum")}, + {('e'), QLatin1String("export_exp_easing")}, + {('e'), QLatin1String("export_file")}, + {('e'), QLatin1String("export_flags")}, + {('e'), QLatin1String("export_flags_2d_navigation")}, + {('e'), QLatin1String("export_flags_2d_physics")}, + {('e'), QLatin1String("export_flags_2d_render")}, + {('e'), QLatin1String("export_flags_3d_navigation")}, + {('e'), QLatin1String("export_flags_3d_physics")}, + {('e'), QLatin1String("export_flags_3d_render")}, + {('e'), QLatin1String("export_flags_avoidance")}, + {('e'), QLatin1String("export_global_dir")}, + {('e'), QLatin1String("export_global_file")}, + {('e'), QLatin1String("export_group")}, + {('e'), QLatin1String("export_multiline")}, + {('e'), QLatin1String("export_node_path")}, + {('e'), QLatin1String("export_placeholder")}, + {('e'), QLatin1String("export_range")}, + {('e'), QLatin1String("export_storage")}, + {('e'), QLatin1String("export_subgroup")}, + {('i'), QLatin1String("icon")}, + {('o'), QLatin1String("onready")}, + {('r'), QLatin1String("rpc")}, + {('s'), QLatin1String("static_unload")}, + {('t'), QLatin1String("tool")}, + {('w'), QLatin1String("warning_ignore")}, + }; +} +void loadGDScriptData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!gdscriptDataInitialized) { + initGDScriptData(); + gdscriptDataInitialized = true; + } + types = gdscript_types; + keywords = gdscript_keywords; + builtin = gdscript_builtin; + literals = gdscript_literals; + other = gdscript_other; +} + +/********************************************************/ +/*** TOML DATA ***************************************/ +/********************************************************/ +static bool TOMLDataInitialized = false; +static QMultiHash TOML_keywords; +static QMultiHash TOML_types; +static QMultiHash TOML_literals; +static QMultiHash TOML_builtin; +static QMultiHash TOML_other; +void initTOMLData() { + TOML_keywords = {}; + TOML_types = {}; + TOML_literals = { + {('f'), QLatin1String("false")}, {('t'), QLatin1String("true")}, + {('n'), QLatin1String("null")}, {('i'), QLatin1String("inf")}, + {('n'), QLatin1String("nan")}, + }; + + TOML_builtin = {}; + TOML_other = {}; +} +void loadTOMLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other) { + if (!TOMLDataInitialized) { + initTOMLData(); + TOMLDataInitialized = true; + } + types = TOML_types; + keywords = TOML_keywords; + builtin = TOML_builtin; + literals = TOML_literals; + other = TOML_other; +} diff --git a/client/qmarkdowntextedit/qownlanguagedata.h b/client/qmarkdowntextedit/qownlanguagedata.h new file mode 100644 index 0000000..8edca7d --- /dev/null +++ b/client/qmarkdowntextedit/qownlanguagedata.h @@ -0,0 +1,270 @@ +/* + * MIT License + * + * Copyright (c) 2019-2021 Waqar Ahmed -- + * + * 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 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 QOWNLANGUAGEDATA_H +#define QOWNLANGUAGEDATA_H + +#include + +/* ------------------------ + * TEMPLATE FOR LANG DATA + * ------------------------- + * + * loadXXXData, where XXX is the language + * keywords are the language keywords e.g, const + * types are built-in types i.e, int, char, var + * literals are words like, true false + * builtin are the library functions + * other can contain any other thing, for e.g, in cpp it contains the + preprocessor + + static const QMultiHash xxx_keywords = { + }; + + static const QMultiHash xxx_types = { + }; + + static const QMultiHash xxx_literals = { + }; + + static const QMultiHash xxx_builtin = { + }; + + static const QMultiHash xxx_other = { + }; + +*/ + +/**********************************************************/ +/* C/C++ Data *********************************************/ +/**********************************************************/ +void loadCppData(QMultiHash &typess, + QMultiHash &keywordss, + QMultiHash &builtins, + QMultiHash &literalss, + QMultiHash &others); + +/**********************************************************/ +/* Shell Data *********************************************/ +/**********************************************************/ +void loadShellData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/**********************************************************/ +/* JS Data *********************************************/ +/**********************************************************/ +void loadJSData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/**********************************************************/ +/* JS Data *********************************************/ +/**********************************************************/ +void loadNixData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/**********************************************************/ +/* PHP Data *********************************************/ +/**********************************************************/ +void loadPHPData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/**********************************************************/ +/* QML Data *********************************************/ +/**********************************************************/ +void loadQMLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/**********************************************************/ +/* Python Data *********************************************/ +/**********************************************************/ +void loadPythonData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** Rust DATA ***********************************/ +/********************************************************/ +void loadRustData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** Java DATA ***********************************/ +/********************************************************/ +void loadJavaData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** C# DATA *************************************/ +/********************************************************/ +void loadCSharpData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** Go DATA *************************************/ +/********************************************************/ +void loadGoData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** V DATA **************************************/ +/********************************************************/ +void loadVData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** SQL DATA ************************************/ +/********************************************************/ +void loadSQLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** System Verilog DATA *************************/ +/********************************************************/ +void loadSystemVerilogData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** JSON DATA ***********************************/ +/********************************************************/ +void loadJSONData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** CSS DATA ***********************************/ +/********************************************************/ +void loadCSSData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** Typescript DATA *********************************/ +/********************************************************/ +void loadTypescriptData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** YAML DATA ***************************************/ +/********************************************************/ +void loadYAMLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** VEX DATA ****************************************/ +/********************************************************/ +void loadVEXData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** CMake DATA **************************************/ +/********************************************************/ +void loadCMakeData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); + +/********************************************************/ +/*** Make DATA ***************************************/ +/********************************************************/ +void loadMakeData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); +/********************************************************/ +/*** Forth DATA **************************************/ +/********************************************************/ +void loadForthData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); +/********************************************************/ +/*** GDScript DATA **************************************/ +/********************************************************/ +void loadGDScriptData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); +/********************************************************/ +/*** TOML DATA **************************************/ +/********************************************************/ +void loadTOMLData(QMultiHash &types, + QMultiHash &keywords, + QMultiHash &builtin, + QMultiHash &literals, + QMultiHash &other); +#endif diff --git a/client/qmarkdowntextedit/qplaintexteditsearchwidget.cpp b/client/qmarkdowntextedit/qplaintexteditsearchwidget.cpp index 54fb975..ec205d7 100644 --- a/client/qmarkdowntextedit/qplaintexteditsearchwidget.cpp +++ b/client/qmarkdowntextedit/qplaintexteditsearchwidget.cpp @@ -1,46 +1,66 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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 "qplaintexteditsearchwidget.h" -#include "ui_qplaintexteditsearchwidget.h" + +#include #include #include -#include -QPlainTextEditSearchWidget::QPlainTextEditSearchWidget(QPlainTextEdit *parent) : - QWidget(parent), - ui(new Ui::QPlainTextEditSearchWidget) -{ +#include "ui_qplaintexteditsearchwidget.h" + +QPlainTextEditSearchWidget::QPlainTextEditSearchWidget(QPlainTextEdit *parent) + : QWidget(parent), + ui(new Ui::QPlainTextEditSearchWidget), + selectionColor(0, 180, 0, 100) { ui->setupUi(this); _textEdit = parent; _darkMode = false; hide(); + ui->searchCountLabel->setStyleSheet(QStringLiteral("* {color: grey}")); + // hiding will leave a open space in the horizontal layout + ui->searchCountLabel->setEnabled(false); + _currentSearchResult = 0; + _searchResultCount = 0; - QObject::connect(ui->closeButton, SIGNAL(clicked()), - this, SLOT(deactivate())); - QObject::connect(ui->searchLineEdit, SIGNAL(textChanged(const QString &)), - this, SLOT(searchLineEditTextChanged(const QString &))); - QObject::connect(ui->searchDownButton, SIGNAL(clicked()), - this, SLOT(doSearchDown())); - QObject::connect(ui->searchUpButton, SIGNAL(clicked()), - this, SLOT(doSearchUp())); - QObject::connect(ui->replaceToggleButton, SIGNAL(toggled(bool)), - this, SLOT(setReplaceMode(bool))); - QObject::connect(ui->replaceButton, SIGNAL(clicked()), - this, SLOT(doReplace())); - QObject::connect(ui->replaceAllButton, SIGNAL(clicked()), - this, SLOT(doReplaceAll())); + connect(ui->closeButton, &QPushButton::clicked, this, + &QPlainTextEditSearchWidget::deactivate); + connect(ui->searchLineEdit, &QLineEdit::textChanged, this, + &QPlainTextEditSearchWidget::searchLineEditTextChanged); + connect(ui->searchDownButton, &QPushButton::clicked, this, + &QPlainTextEditSearchWidget::doSearchDown); + connect(ui->searchUpButton, &QPushButton::clicked, this, + &QPlainTextEditSearchWidget::doSearchUp); + connect(ui->replaceToggleButton, &QPushButton::toggled, this, + &QPlainTextEditSearchWidget::setReplaceMode); + connect(ui->replaceButton, &QPushButton::clicked, this, + &QPlainTextEditSearchWidget::doReplace); + connect(ui->replaceAllButton, &QPushButton::clicked, this, + &QPlainTextEditSearchWidget::doReplaceAll); + + connect(&_debounceTimer, &QTimer::timeout, this, + &QPlainTextEditSearchWidget::performSearch); installEventFilter(this); ui->searchLineEdit->installEventFilter(this); @@ -52,7 +72,7 @@ QPlainTextEditSearchWidget::QPlainTextEditSearchWidget(QPlainTextEdit *parent) : ui->buttonFrame->layout()->setSpacing(9); // set the margin to 0 for the top buttons for OS X - QString buttonStyle = "QPushButton {margin: 0}"; + QString buttonStyle = QStringLiteral("QPushButton {margin: 0}"); ui->closeButton->setStyleSheet(buttonStyle); ui->searchDownButton->setStyleSheet(buttonStyle); ui->searchUpButton->setStyleSheet(buttonStyle); @@ -61,25 +81,9 @@ QPlainTextEditSearchWidget::QPlainTextEditSearchWidget(QPlainTextEdit *parent) : #endif } -QPlainTextEditSearchWidget::~QPlainTextEditSearchWidget() { - delete ui; -} +QPlainTextEditSearchWidget::~QPlainTextEditSearchWidget() { delete ui; } -void QPlainTextEditSearchWidget::activate() { - setReplaceMode(false); - show(); - - // preset the selected text as search text if there is any and there is no - // other search text - QString selectedText = _textEdit->textCursor().selectedText(); - if (!selectedText.isEmpty() && ui->searchLineEdit->text().isEmpty()) { - ui->searchLineEdit->setText(selectedText); - } - - ui->searchLineEdit->setFocus(); - ui->searchLineEdit->selectAll(); - doSearchDown(); -} +void QPlainTextEditSearchWidget::activate() { activate(true); } void QPlainTextEditSearchWidget::activateReplace() { // replacing is prohibited if the text edit is readonly @@ -94,7 +98,13 @@ void QPlainTextEditSearchWidget::activateReplace() { } void QPlainTextEditSearchWidget::deactivate() { + stopDebounce(); + hide(); + + // Clear the search extra selections when closing the search bar + clearSearchExtraSelections(); + _textEdit->setFocus(); } @@ -109,29 +119,33 @@ void QPlainTextEditSearchWidget::setReplaceMode(bool enabled) { bool QPlainTextEditSearchWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); + auto *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Escape) { deactivate(); return true; - } else if ((keyEvent->modifiers().testFlag(Qt::ShiftModifier) && - (keyEvent->key() == Qt::Key_Return)) || - (keyEvent->key() == Qt::Key_Up)) { + } else if ((!_debounceTimer.isActive() && + keyEvent->modifiers().testFlag(Qt::ShiftModifier) && + (keyEvent->key() == Qt::Key_Return)) || + (keyEvent->key() == Qt::Key_Up)) { doSearchUp(); return true; - } else if ((keyEvent->key() == Qt::Key_Return) || - (keyEvent->key() == Qt::Key_Down)) { + } else if (!_debounceTimer.isActive() && + ((keyEvent->key() == Qt::Key_Return) || + (keyEvent->key() == Qt::Key_Down))) { doSearchDown(); return true; - } else if (keyEvent->key() == Qt::Key_F3) { + } else if (!_debounceTimer.isActive() && + keyEvent->key() == Qt::Key_F3) { doSearch(!keyEvent->modifiers().testFlag(Qt::ShiftModifier)); return true; } -// if ((obj == ui->replaceLineEdit) && (keyEvent->key() == Qt::Key_Tab) -// && ui->replaceToggleButton->isChecked()) { -// ui->replaceLineEdit->setFocus(); -// } + // if ((obj == ui->replaceLineEdit) && (keyEvent->key() == + // Qt::Key_Tab) + // && ui->replaceToggleButton->isChecked()) { + // ui->replaceLineEdit->setFocus(); + // } return false; } @@ -139,19 +153,74 @@ bool QPlainTextEditSearchWidget::eventFilter(QObject *obj, QEvent *event) { return QWidget::eventFilter(obj, event); } -void QPlainTextEditSearchWidget::searchLineEditTextChanged(const QString &arg1) { - Q_UNUSED(arg1); +void QPlainTextEditSearchWidget::searchLineEditTextChanged( + const QString &arg1) { + _searchTerm = arg1; + + if (_debounceTimer.interval() != 0 && !_searchTerm.isEmpty()) { + _debounceTimer.start(); + ui->searchDownButton->setEnabled(false); + ui->searchUpButton->setEnabled(false); + } else { + performSearch(); + } +} + +void QPlainTextEditSearchWidget::performSearch() { + doSearchCount(); + updateSearchExtraSelections(); doSearchDown(); } -void QPlainTextEditSearchWidget::doSearchUp() { - doSearch(false); +void QPlainTextEditSearchWidget::clearSearchExtraSelections() { + _searchExtraSelections.clear(); + setSearchExtraSelections(); } -void QPlainTextEditSearchWidget::doSearchDown() { - doSearch(true); +void QPlainTextEditSearchWidget::updateSearchExtraSelections() { + _searchExtraSelections.clear(); + const auto textCursor = _textEdit->textCursor(); + _textEdit->moveCursor(QTextCursor::Start); + const QColor color = selectionColor; + QTextCharFormat extraFmt; + extraFmt.setBackground(color); + int findCounter = 0; + const int searchMode = ui->modeComboBox->currentIndex(); + + while (doSearch(true, false, false)) { + findCounter++; + + // prevent infinite loops from regular expression searches like "$", "^" + // or "\b" + if (searchMode == RegularExpressionMode && findCounter >= 10000) { + break; + } + + QTextEdit::ExtraSelection extra = QTextEdit::ExtraSelection(); + extra.format = extraFmt; + + extra.cursor = _textEdit->textCursor(); + _searchExtraSelections.append(extra); + } + + _textEdit->setTextCursor(textCursor); + this->setSearchExtraSelections(); } +void QPlainTextEditSearchWidget::setSearchExtraSelections() const { + this->_textEdit->setExtraSelections(this->_searchExtraSelections); +} + +void QPlainTextEditSearchWidget::stopDebounce() { + _debounceTimer.stop(); + ui->searchDownButton->setEnabled(true); + ui->searchUpButton->setEnabled(true); +} + +void QPlainTextEditSearchWidget::doSearchUp() { doSearch(false); } + +void QPlainTextEditSearchWidget::doSearchDown() { doSearch(true); } + bool QPlainTextEditSearchWidget::doReplace(bool forAll) { if (_textEdit->isReadOnly()) { return false; @@ -163,18 +232,18 @@ bool QPlainTextEditSearchWidget::doReplace(bool forAll) { return false; } - int searchMode = ui->modeComboBox->currentIndex(); + const int searchMode = ui->modeComboBox->currentIndex(); if (searchMode == RegularExpressionMode) { QString text = cursor.selectedText(); - text.replace(QRegExp(ui->searchLineEdit->text()), - ui->replaceLineEdit->text()); + text.replace(QRegularExpression(ui->searchLineEdit->text()), + ui->replaceLineEdit->text()); cursor.insertText(text); } else { cursor.insertText(ui->replaceLineEdit->text()); } if (!forAll) { - int position = cursor.position(); + const int position = cursor.position(); if (!doSearch(true)) { // restore the last cursor position if text wasn't found any more @@ -195,72 +264,238 @@ void QPlainTextEditSearchWidget::doReplaceAll() { _textEdit->moveCursor(QTextCursor::Start); // replace until everything to the bottom is replaced - while (doSearch(true, false) && doReplace(true)) {} + while (doSearch(true, false) && doReplace(true)) { + } } /** * @brief Searches for text in the text edit * @returns true if found */ -bool QPlainTextEditSearchWidget::doSearch(bool searchDown, bool allowRestartAtTop) { - QString text = ui->searchLineEdit->text(); +bool QPlainTextEditSearchWidget::doSearch(bool searchDown, + bool allowRestartAtTop, + bool updateUI) { + if (_debounceTimer.isActive()) { + stopDebounce(); + } + + const QString text = ui->searchLineEdit->text(); + + if (text.isEmpty()) { + if (updateUI) { + ui->searchLineEdit->setStyleSheet(QLatin1String("")); + } - if (text == "") { - ui->searchLineEdit->setStyleSheet(""); return false; } - int searchMode = ui->modeComboBox->currentIndex(); + const int searchMode = ui->modeComboBox->currentIndex(); + const bool caseSensitive = ui->matchCaseSensitiveButton->isChecked(); - QFlags options = searchDown ? - QTextDocument::FindFlag(0) - : QTextDocument::FindBackward; + QFlags options = + searchDown ? QTextDocument::FindFlag(0) : QTextDocument::FindBackward; if (searchMode == WholeWordsMode) { options |= QTextDocument::FindWholeWords; } - if (ui->matchCaseSensitiveButton->isChecked()) { + if (caseSensitive) { options |= QTextDocument::FindCaseSensitively; } - bool found; - if (searchMode == RegularExpressionMode) { - found = _textEdit->find(QRegExp(text), options); - } else { - found = _textEdit->find(text, options); + // block signal to reduce too many signals being fired and too many updates + _textEdit->blockSignals(true); + + bool found = + searchMode == RegularExpressionMode + ? +#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) + _textEdit->find( + QRegularExpression( + text, caseSensitive + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption), + options) + : +#else + _textEdit->find(QRegExp(text, caseSensitive ? Qt::CaseSensitive + : Qt::CaseInsensitive), + options) + : +#endif + _textEdit->find(text, options); + + _textEdit->blockSignals(false); + + if (found) { + const int result = + searchDown ? ++_currentSearchResult : --_currentSearchResult; + _currentSearchResult = std::min(result, _searchResultCount); + + updateSearchCountLabelText(); } // start at the top (or bottom) if not found if (!found && allowRestartAtTop) { - _textEdit->moveCursor( - searchDown ? QTextCursor::Start : QTextCursor::End); - found = _textEdit->find(text, options); + _textEdit->moveCursor(searchDown ? QTextCursor::Start + : QTextCursor::End); + found = + searchMode == RegularExpressionMode + ? +#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) + _textEdit->find( + QRegularExpression( + text, caseSensitive + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption), + options) + : +#else + _textEdit->find( + QRegExp(text, caseSensitive ? Qt::CaseSensitive + : Qt::CaseInsensitive), + options) + : +#endif + _textEdit->find(text, options); + + if (found && updateUI) { + _currentSearchResult = searchDown ? 1 : _searchResultCount; + updateSearchCountLabelText(); + } } - QRect rect = _textEdit->cursorRect(); - QMargins margins = _textEdit->layout()->contentsMargins(); - int searchWidgetHotArea = _textEdit->height() - this->height(); - int marginBottom = (rect.y() > searchWidgetHotArea) ? (this->height() + 10) - : 0; + if (updateUI) { + const QRect rect = _textEdit->cursorRect(); + QMargins margins = _textEdit->layout()->contentsMargins(); + const int searchWidgetHotArea = _textEdit->height() - this->height(); + const int marginBottom = + (rect.y() > searchWidgetHotArea) ? (this->height() + 10) : 0; - // move the search box a bit up if we would block the search result - if (margins.bottom() != marginBottom) { - margins.setBottom(marginBottom); - _textEdit->layout()->setContentsMargins(margins); + // move the search box a bit up if we would block the search result + if (margins.bottom() != marginBottom) { + margins.setBottom(marginBottom); + _textEdit->layout()->setContentsMargins(margins); + } + + // add a background color according if we found the text or not + const QString bgColorCode = _darkMode + ? (found ? QStringLiteral("#135a13") + : QStringLiteral("#8d2b36")) + : found ? QStringLiteral("#D5FAE2") + : QStringLiteral("#FAE9EB"); + const QString fgColorCode = + _darkMode ? QStringLiteral("#cccccc") : QStringLiteral("#404040"); + + ui->searchLineEdit->setStyleSheet( + QStringLiteral("* { background: ") + bgColorCode + + QStringLiteral("; color: ") + fgColorCode + QStringLiteral("; }")); + + // restore the search extra selections after the find command + this->setSearchExtraSelections(); } - // add a background color according if we found the text or not - QString colorCode = found ? "#D5FAE2" : "#FAE9EB"; - - if (_darkMode) { - colorCode = found ? "#135a13" : "#8d2b36"; - } - - ui->searchLineEdit->setStyleSheet("* { background: " + colorCode + "; }"); - return found; } +/** + * @brief Counts the search results + */ +void QPlainTextEditSearchWidget::doSearchCount() { + // Note that we are moving the anchor, so the search will start from the top + // again! Alternative: Restore cursor position afterward, but then we will + // not know + // at what _currentSearchResult we currently are + _textEdit->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor); + + bool found; + _searchResultCount = 0; + _currentSearchResult = 0; + const int searchMode = ui->modeComboBox->currentIndex(); + + do { + found = doSearch(true, false, false); + if (found) { + _searchResultCount++; + } + + // prevent infinite loops from regular expression searches like "$", "^" + // or "\b" + if (searchMode == RegularExpressionMode && + _searchResultCount >= 10000) { + break; + } + } while (found); + + updateSearchCountLabelText(); +} + void QPlainTextEditSearchWidget::setDarkMode(bool enabled) { _darkMode = enabled; } + +void QPlainTextEditSearchWidget::setSearchText(const QString &searchText) { + ui->searchLineEdit->setText(searchText); +} + +void QPlainTextEditSearchWidget::setSearchMode(SearchMode searchMode) { + ui->modeComboBox->setCurrentIndex(searchMode); +} + +void QPlainTextEditSearchWidget::setDebounceDelay(uint debounceDelay) { + _debounceTimer.setInterval(static_cast(debounceDelay)); +} + +void QPlainTextEditSearchWidget::activate(bool focus) { + setReplaceMode(ui->modeComboBox->currentIndex() != + SearchMode::PlainTextMode); + show(); + + // preset the selected text as search text if there is any and there is no + // other search text + const QString selectedText = _textEdit->textCursor().selectedText(); + if (!selectedText.isEmpty() && ui->searchLineEdit->text().isEmpty()) { + ui->searchLineEdit->setText(selectedText); + } + + if (focus) { + ui->searchLineEdit->setFocus(); + } + + ui->searchLineEdit->selectAll(); + updateSearchExtraSelections(); + doSearchDown(); +} + +void QPlainTextEditSearchWidget::reset() { + ui->searchLineEdit->clear(); + setSearchMode(SearchMode::PlainTextMode); + setReplaceMode(false); + ui->searchCountLabel->setEnabled(false); +} + +void QPlainTextEditSearchWidget::updateSearchCountLabelText() { + ui->searchCountLabel->setEnabled(true); + ui->searchCountLabel->setText(QStringLiteral("%1/%2").arg( + _currentSearchResult == 0 ? QChar('-') + : QString::number(_currentSearchResult), + _searchResultCount == 0 ? QChar('-') + : QString::number(_searchResultCount))); +} + +void QPlainTextEditSearchWidget::setSearchSelectionColor(const QColor &color) { + selectionColor = color; +} + +void QPlainTextEditSearchWidget::on_modeComboBox_currentIndexChanged( + int index) { + Q_UNUSED(index) + doSearchCount(); + doSearchDown(); +} + +void QPlainTextEditSearchWidget::on_matchCaseSensitiveButton_toggled( + bool checked) { + Q_UNUSED(checked) + doSearchCount(); + doSearchDown(); +} diff --git a/client/qmarkdowntextedit/qplaintexteditsearchwidget.h b/client/qmarkdowntextedit/qplaintexteditsearchwidget.h index aaeb8b0..1af752b 100644 --- a/client/qmarkdowntextedit/qplaintexteditsearchwidget.h +++ b/client/qmarkdowntextedit/qplaintexteditsearchwidget.h @@ -1,51 +1,73 @@ /* - * Copyright (c) 2014-2019 Patrizio Bekerle -- http://www.bekerle.com + * MIT License * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * Copyright (c) 2014-2025 Patrizio Bekerle -- * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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 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. */ #pragma once -#include #include +#include +#include namespace Ui { class QPlainTextEditSearchWidget; } -class QPlainTextEditSearchWidget : public QWidget -{ +class QPlainTextEditSearchWidget : public QWidget { Q_OBJECT -public: - enum SearchMode { - PlainTextMode, - WholeWordsMode, - RegularExpressionMode - }; + public: + enum SearchMode { PlainTextMode, WholeWordsMode, RegularExpressionMode }; - explicit QPlainTextEditSearchWidget(QPlainTextEdit *parent = 0); - bool doSearch(bool searchDown = true, bool allowRestartAtTop = true); + explicit QPlainTextEditSearchWidget(QPlainTextEdit *parent = nullptr); + bool doSearch(bool searchDown = true, bool allowRestartAtTop = true, + bool updateUI = true); void setDarkMode(bool enabled); ~QPlainTextEditSearchWidget(); -private: - Ui::QPlainTextEditSearchWidget *ui; + void setSearchText(const QString &searchText); + void setSearchMode(SearchMode searchMode); + void setDebounceDelay(uint debounceDelay); + void activate(bool focus); + void clearSearchExtraSelections(); + void updateSearchExtraSelections(); -protected: + private: + Ui::QPlainTextEditSearchWidget *ui; + int _searchResultCount; + int _currentSearchResult; + QList _searchExtraSelections; + QColor selectionColor; + QTimer _debounceTimer; + QString _searchTerm; + void setSearchExtraSelections() const; + void stopDebounce(); + + protected: QPlainTextEdit *_textEdit; bool _darkMode; - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject *obj, QEvent *event) override; -public slots: + public Q_SLOTS: void activate(); void deactivate(); void doSearchDown(); @@ -54,7 +76,15 @@ public slots: void activateReplace(); bool doReplace(bool forAll = false); void doReplaceAll(); + void reset(); + void doSearchCount(); -protected slots: + protected Q_SLOTS: void searchLineEditTextChanged(const QString &arg1); + void performSearch(); + void updateSearchCountLabelText(); + void setSearchSelectionColor(const QColor &color); + private Q_SLOTS: + void on_modeComboBox_currentIndexChanged(int index); + void on_matchCaseSensitiveButton_toggled(bool checked); }; diff --git a/client/qmarkdowntextedit/qplaintexteditsearchwidget.ui b/client/qmarkdowntextedit/qplaintexteditsearchwidget.ui index efbba09..78ccb1d 100644 --- a/client/qmarkdowntextedit/qplaintexteditsearchwidget.ui +++ b/client/qmarkdowntextedit/qplaintexteditsearchwidget.ui @@ -26,10 +26,85 @@ 0 + + + + Find in text + + + + + + + Replace with + + + + + + + -/- + + + + + + + Find: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + Search backward + + + + + + + :/media/go-top.svg:/media/go-top.svg + + + true + + + + + + + Replace: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Close search + + + + + + + :/media/window-close.svg:/media/window-close.svg + + + true + + + + - replace text + Advanced search / replace text @@ -46,44 +121,10 @@ - - - - Find: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - close search - - - - - - - :/media/window-close.svg:/media/window-close.svg - - - true - - - - - - - find in text - - - - + - search forward + Search forward @@ -97,41 +138,37 @@ - - + + - search backward + Match case sensitive - - :/media/go-top.svg:/media/go-top.svg + + :/media/format-text-superscript.svg:/media/format-text-superscript.svg + + + true true - - - - replace with - - - - - + + - Replace: + Mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + QFrame::NoFrame @@ -147,7 +184,7 @@ 0 - 9 + 0 @@ -183,6 +220,9 @@ + + Replace one text occurrence + Replace @@ -193,8 +233,11 @@ + + Replace all text occurrences + - Replace All + Replace all false @@ -204,36 +247,6 @@ - - - - Mode: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Match case sensitive - - - - - - - :/media/format-text-superscript.svg:/media/format-text-superscript.svg - - - true - - - true - - - diff --git a/client/qmarkdowntextedit/screenshot.png b/client/qmarkdowntextedit/screenshot.png index ca3bf87..861749c 100644 Binary files a/client/qmarkdowntextedit/screenshot.png and b/client/qmarkdowntextedit/screenshot.png differ diff --git a/client/qmarkdowntextedit/scripts/clang-format-project.sh b/client/qmarkdowntextedit/scripts/clang-format-project.sh new file mode 100755 index 0000000..07bca54 --- /dev/null +++ b/client/qmarkdowntextedit/scripts/clang-format-project.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +# A tool to run clang-format on the entire project +# +# Some inspirations were taken from https://github.com/eklitzke/clang-format-all + +# Variable that will hold the name of the clang-format command +FMT="" + +# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent +# that the version number be part of the command. We prefer clang-format if +# that's present, otherwise we work backwards from highest version to lowest +# version. +for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do + if which "$clangfmt" &>/dev/null; then + FMT="$clangfmt" + break + fi +done + +# Check if we found a working clang-format +if [ -z "$FMT" ]; then + echo "failed to find clang-format" + exit 1 +fi + +$FMT -i *.cpp +$FMT -i *.h diff --git a/client/qmarkdowntextedit/trans/qmarkdowntextedit_es.qm b/client/qmarkdowntextedit/trans/qmarkdowntextedit_es.qm new file mode 100644 index 0000000..ea421e5 Binary files /dev/null and b/client/qmarkdowntextedit/trans/qmarkdowntextedit_es.qm differ diff --git a/client/qmarkdowntextedit/trans/qmarkdowntextedit_es.ts b/client/qmarkdowntextedit/trans/qmarkdowntextedit_es.ts new file mode 100644 index 0000000..d6a15b6 --- /dev/null +++ b/client/qmarkdowntextedit/trans/qmarkdowntextedit_es.ts @@ -0,0 +1,92 @@ + + + + + QPlainTextEditSearchWidget + + + Find in text + Buscar en el texto + + + + Replace with + Reemplazar por + + + + Find: + Buscar: + + + + Search backward + Buscar hacia atrás + + + + Replace: + Reemplazar: + + + + Close search + Cerrar búsqueda + + + + Advanced search / replace text + Búsqueda avanzada / reemplazar texto + + + + Search forward + Buscar hacia adelante + + + + Match case sensitive + Distingue mayúsculas y minúsculas + + + + Mode: + Modo: + + + + Plain text + Texto plano + + + + Whole words + Palabras enteras + + + + Regular expression + Expresión regular + + + + Replace one text occurrence + Reemplazar una ocurrencia del texto + + + + Replace + Reemplazar + + + + Replace all text occurrences + Reemplazar todas las ocurrencias del texto + + + + Replace all + Reemplazar todo + + + diff --git a/client/qmarkdowntextedit/trans/qmarkdowntextedit_ur.qm b/client/qmarkdowntextedit/trans/qmarkdowntextedit_ur.qm new file mode 100644 index 0000000..ce02ba8 Binary files /dev/null and b/client/qmarkdowntextedit/trans/qmarkdowntextedit_ur.qm differ diff --git a/client/qmarkdowntextedit/trans/qmarkdowntextedit_ur.ts b/client/qmarkdowntextedit/trans/qmarkdowntextedit_ur.ts new file mode 100644 index 0000000..0f90b57 --- /dev/null +++ b/client/qmarkdowntextedit/trans/qmarkdowntextedit_ur.ts @@ -0,0 +1,57 @@ + + + + + QPlainTextEditSearchWidget + + + close search + تلاش بند کریں + + + + Find: + تلاش: + + + + replace text + ٹیکصٹ بدلیں + + + + find in text + متن میں تلاش کریں + + + + search forward + آگے تلاش کریں + + + + search backward + پیچھے تلاش کریں + + + + replace with + بدلیں اس سے + + + + Replace: + بدلیں: + + + + Replace + بدلیں + + + + Replace All + تمام کو بدل دیں + + + diff --git a/client/qmarkdowntextedit/trans/qmarkdowntextedit_zh_CN.qm b/client/qmarkdowntextedit/trans/qmarkdowntextedit_zh_CN.qm new file mode 100644 index 0000000..bea6b74 Binary files /dev/null and b/client/qmarkdowntextedit/trans/qmarkdowntextedit_zh_CN.qm differ diff --git a/client/qmarkdowntextedit/trans/qmarkdowntextedit_zh_CN.ts b/client/qmarkdowntextedit/trans/qmarkdowntextedit_zh_CN.ts new file mode 100644 index 0000000..b9eb4b7 --- /dev/null +++ b/client/qmarkdowntextedit/trans/qmarkdowntextedit_zh_CN.ts @@ -0,0 +1,92 @@ + + + + + QPlainTextEditSearchWidget + + + Find in text + 在文本中查找 + + + + Replace with + 替换为 + + + + Find: + 查找 + + + + Search backward + 上一个匹配项 + + + + Replace: + 替换 + + + + Close search + 关闭搜索框 + + + + Advanced search / replace text + 高级搜索/替换 + + + + Search forward + 下一个匹配项 + + + + Match case sensitive + 区分大小写 + + + + Mode: + 模式 + + + + Plain text + 字符匹配 + + + + Whole words + 全字匹配 + + + + Regular expression + 正则表达式 + + + + Replace one text occurrence + 替换第一个匹配的文本 + + + + Replace + 替换 + + + + Replace all text occurrences + 替换所有匹配的文本 + + + + Replace all + 全部替换 + + + diff --git a/client/qmarkdowntextedit/treefmt.toml b/client/qmarkdowntextedit/treefmt.toml new file mode 100644 index 0000000..3e490d8 --- /dev/null +++ b/client/qmarkdowntextedit/treefmt.toml @@ -0,0 +1,39 @@ +# https://github.com/numtide/treefmt +# https://github.com/numtide/treefmt-nix + +on-unmatched = "info" + +[formatter.clang-format] +command = "clang-format" + +# Only target the exact directories we want +includes = [ + "*.cpp", + "*.h", +] + +[formatter.prettier] +command = "prettier" +options = ["--write"] +includes = ["*.md", "*.yaml", "*.yml"] + +[formatter.shfmt] +command = "shfmt" +excludes = [] +includes = ["*.sh", "*.bash", "*.envrc", "*.envrc.*"] +options = ["-s", "-w", "-i", "2"] + +[formatter.just] +command = "just" +includes = ["*.just"] + +[formatter.taplo] +command = "taplo" +includes = ["*.toml"] +options = ["format"] + +[formatter.nixfmt-rfc-style] +command = "nixfmt" +excludes = [] +includes = ["*.nix"] +options = [] diff --git a/client/task.cpp b/client/task.cpp index 4a60a65..5faea0f 100644 --- a/client/task.cpp +++ b/client/task.cpp @@ -608,7 +608,7 @@ int TimeLine::getTime(int year, int month, int day, std::vector* int // Find range of related records [lowest, higher) TimeArray::iterator lowest = std::lower_bound(mData.begin(), mData.end(), d, [] (const TimeRecord& tr, const QDate& d) { - return tr.endTime() < QDateTime(d).toTime_t(); + return tr.endTime() < QDateTime(d, QTime()).toSecsSinceEpoch(); }); //TimeArray::iterator higher = std::upper_bound(mData.begin(), mData.end(), d, [] (const QDate& d, const TimeRecord& tr) { return tr.startTime().toLocalTime().date() < d;}); diff --git a/client/timeintervaldlg.cpp b/client/timeintervaldlg.cpp index 121b512..aa58678 100644 --- a/client/timeintervaldlg.cpp +++ b/client/timeintervaldlg.cpp @@ -47,7 +47,9 @@ QDateTime TimeIntervalDlg::finishDate() void TimeIntervalDlg::accept() { // Insert interval - mModel->insertInterval(TimeRecord(startDate().toUTC().toTime_t(), finishDate().toUTC().toTime_t(), mTimeline->taskId())); + mModel->insertInterval(TimeRecord(startDate().toUTC().toSecsSinceEpoch(), + finishDate().toUTC().toSecsSinceEpoch(), + mTimeline->taskId())); emit accepted(); close(); } @@ -68,7 +70,9 @@ void TimeIntervalDlg::closeEvent(QCloseEvent *event) bool TimeIntervalDlg::validate() { assert(mTimeline); - return !mTimeline->hasIntersection(TimeRecord(startDate().toUTC().toTime_t(), finishDate().toUTC().toTime_t(), mTimeline->taskId())); + return !mTimeline->hasIntersection(TimeRecord(startDate().toUTC().toSecsSinceEpoch(), + finishDate().toUTC().toSecsSinceEpoch(), + mTimeline->taskId())); } void TimeIntervalDlg::dataChanged(const QDateTime& changed) diff --git a/client/timetreemodel.cpp b/client/timetreemodel.cpp index a3d8ba8..ca8f425 100644 --- a/client/timetreemodel.cpp +++ b/client/timetreemodel.cpp @@ -275,7 +275,7 @@ int TimeTreeModel::columnCount(const QModelIndex &parent) const static QString monthToString(int month) { - return QDate::longMonthName(month); + return QLocale::system().monthName(month); } QVariant TimeTreeModel::data(const QModelIndex &index, int role) const diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh index 8c5b05d..8feb42d 100755 --- a/scripts/build_linux.sh +++ b/scripts/build_linux.sh @@ -2,9 +2,9 @@ # I use this script on two different hosts so there are logic to find proper Qt installation -export QT_HOME=/home/$USER/qt5.15/5.15.2/gcc_64 +export QT_HOME=/home/$USER/tools/qt/6.8.0/gcc_64 if [ ! -d "$QT_HOME" ] ; then - export QT_HOME=/home/$USER/qt5.15/5.15.2/gcc_64 + export QT_HOME=/home/$USER/tools/qt/6.8.0/gcc_64 fi # Build .appimage diff --git a/scripts/linuxdeployqt b/scripts/linuxdeployqt index 2d65297..be8cf18 100755 Binary files a/scripts/linuxdeployqt and b/scripts/linuxdeployqt differ